多线程(一)
进程和线程
并行
多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
并发
通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。
一个程序(进程)可以同时有很多线程,但同一时间点只能执行其中一条线(单核CPU)
多核cpu使用多线程,可以提升运行速度
案例
一天考4科
分着考正常执行一起考来回换着做就是多线程,所以多线程消耗内存空间,也浪费时间
某人的一天:吃饭,取快递,写作业
实现和开启
要让一段代码具备多线程的能力
实现Thread类
public class Eat extends Thread {
String name;
public Eat(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(name + ":" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
实现Thread接口
public class Work implements Runnable {
String subject;
public Work(String subject) {
this.subject = subject;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(subject + "zuoye:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
都是要在run方法中
代码具备并发能力之后,想以多线程的方式开启,不能直接调用,得使用Thread类的start方法,如果是接口实现,就得重新构造一个Thread类的对象,否则就没有start方法了
public class Test {
public static void main(String[] args) {
Eat e1 = new Eat("e1");
Eat e2 = new Eat("e2");
e1.start();
e2.start();
// Work w1 = new Work("English");
// Work w2 = new Work("math");
// Thread t1 = new Thread(w1);
// Thread t2 = new Thread(w2);
// t1.start();
// t2.start();
}
}
生命周期
1.新建状态
创建线程对象(new Thread()),不可运行start()
2.就绪状态
线程进入线程队列排队,等待CPU服务 获取CPU资源
3.运行状态
自动调用线程对象的run方法run方法正常执行完毕
4.阻塞状态
人为控制,IO阻塞,锁,sleep等IO获取到资源,获得锁,sleep时间到了等
5.死亡状态
不会再继续运行,内存空间也自动销毁,调用stop方法也可以,但是不要去做
各种状态之间,只有运行和就绪是双向的,可以互相转换
线程的创建是最消耗资源的
线程调度
强制运行,join
多线程并发中,让其中一条线程,强制运行,其他的无法运行,必须等待这个线程运行完成后才能继续运行
例如:
主线程先执行5次,t1开启,两条线程并发执行:如果加上join那么,e1执行,就不允许其他的执行,直到e1的run方法全部结束
public class TestJoin {
public static void main(String[] args) {
try {
ThreadA t1 = new ThreadA("t1");
for (int i = 0; i < 10; i++) {
if (i == 5) {
t1.start();
t1.join();
}
Thread.sleep(1000);
System.out.println("main" + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class ThreadA extends Thread {
public ThreadA(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("这是 : " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
中断线程:一个线程运行时,另外一个线程可以通过interrupt方法中断其运行状态
public class TestInterrupt implements Runnable{
@Override
public void run() {
System.out.println("闭关修炼");
try {
Thread.sleep(3000);
System.out.println("羽化成仙");
} catch (InterruptedException e) {
System.out.println("走火入魔");
return;
}
System.out.println("修炼完毕");
}
}
public class Test2 {
public static void main(String[] args) {
TestInterrupt t = new TestInterrupt();
Thread tt = new Thread(t);
tt.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
tt.interrupt();
}
}
线程的礼让:使用yield方法将一个线程的操作暂时终止让给其他线程
public class TestYield {
public static void main(String[] args) {
new Thread(()->{
for(int i=0; i<100; i++) {
System.out.println("lambda....."+i);
}
}).start();
for(int i=1; i<=100; i++) {
if(i%20 == 0){
Thread.yield();//main线程礼让
}
System.out.println("main...."+i);
}
}
}