一:为什么出现多线程?
1. 线程是指,一段代码的运行(cpu,代码,数据)。但是,生产中,我们真实情况,数据都是并发传送的,所以,我们仅仅使用一条路来处理,就会发生数据堵塞的情况。所以,我们使用多线程,启动多条路来跑代码。
二:什么是多线程?
1. 线程和进程,代码的区别。
(1)代码是静态的概念。
(2)进程是动态的概念。在运行的时候,包括cpu,代码,数据。本质上讲,进程是分配资源的单位。
(3)线程是指操作系统能够调用的最小的单位。一个进程可以包含多个进程。本质上讲,线程是调度和执行的单位。
三:怎么使用多线程?
1.继承Thread类实现。
(1)类继承Thread。
(2)类中实现run方法。
(3)在主函数中,创建对象。
(4)对象调用start方法。
package day04_thread;
//第一种方法,继承Thread类实现
public class Thread_test extends Thread{
int i;
public Thread_test(int i) {
this.i = i;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
@Override
public void run() {
System.out.println("这次运行是第"+i+"次!");
}
}
package day04_thread;
public class Thread_main {
public static void main(String[] args) {
Thread_test thread_test = new Thread_test(1);
Thread_test thread_test1 = new Thread_test(2);
Thread_test thread_test2 = new Thread_test(3);
thread_test.start();
thread_test1.start();
thread_test2.start();
}
}
2.实现Runnable接口。
(1)类实现接口Runnable。
(2)类中实现run方法。
(3)在主函数中,创建对象。
(4)创建Thread对象。
(5)对象调用start方法。
package day04_thread;
public class Thread_Runnable implements Runnable{
String name;
public Thread_Runnable(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("这个人名字是"+name);
}
}
package day04_thread;
public class Thread_main {
public static void main(String[] args) {
Thread_Runnable zzy = new Thread_Runnable("zzy");
Thread thread = new Thread(zzy);
Thread_Runnable zzx = new Thread_Runnable("zzx");
Thread thread1 = new Thread(zzx);
Thread_Runnable iop = new Thread_Runnable("iop");
Thread thread2 = new Thread(iop);
thread.start();
thread1.start();
thread2.start();
}
}
3.实现Callable接口。
(1)类实现接口Callnable。
(2)类中实现call方法。
(3)在主函数中,创建对象。
(4)创建FutureTask对象。
(5)创建Thread对象。
(6)对象调用start方法。
package day04_thread;
import java.util.concurrent.Callable;
public class Thread_Callable implements Callable {
int i;
public Thread_Callable(int i) {
this.i = i;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
@Override
public Object call() throws Exception {
System.out.println(i);
return null;
}
}
package day04_thread;
import com.sun.org.apache.xpath.internal.functions.FuncTrue;
import java.util.concurrent.FutureTask;
public class Thread_main {
public static void main(String[] args) {
Thread_Callable thread_callable = new Thread_Callable(1);
FutureTask futureTask = new FutureTask<>(thread_callable);
Thread thread = new Thread(futureTask);
Thread_Callable thread_callable1 = new Thread_Callable(2);
FutureTask futureTask1 = new FutureTask<>(thread_callable1);
Thread thread1 = new Thread(futureTask1);
Thread_Callable thread_callable2 = new Thread_Callable(3);
FutureTask futureTask2 = new FutureTask<>(thread_callable2);
Thread thread2 = new Thread(futureTask2);
thread.start();
thread1.start();
thread2.start();
}
}
4.线程池。
5.对比。
(1)Thread:继承方式,不建议使用,因为Java是单继承的继承了Thread就没办法继承其它类了,不够灵活。
(2)Runnable:实现接口,比Thread类更加灵活,没有单继承的限制Callable: Thread和Runnable都是重写的run()方法并目没有返回值。
(3)callable是重写的call0方法并且有返回值并可以借助FutureTask类来判断线程是否已经执行完毕或者取消线程执行当线程不需要返回值时使用Runnable,需要返回值时就使用Callable。
6.线程的方法。
优先级分为1-10,优先级越高,说明先执行的概率越大,但是不是一定执行它。
四:线程多种状态
1.新建状态。使用new关键字和其他子类,建立一个线程。
2.就绪状态。在调用start。
3.运行状态。在执行run()之后。
4.阻塞状态。当一个线程执行了sleep(失眠),suspend(挂起)等方法市区资源
(1)sleep,方法需要指定等待的时间,之后在进行执行。参数是毫秒。
@Override
public Object call() throws Exception {
System.out.println("iopokdo");
if(i==1) {Thread.sleep(5000);}
System.out.println("diyi"+i);
return null;
}
(2)yield,让当前线程重新回到就绪状态。
(3)join,当遇到这个方法,其他线程让出资源,先让这个线程跑完之后,在去跑其他线程。
5.死亡状态。当程序运行结束之后。另外一种,执行stop。
五:锁
1. synchronized方法 和 synchronized块。
synchronized方法
synchronized块
后者对比前者效率更高。