在了解多线程之前,要先了解进程。
进程:程序的运行过程,是动态的,有就绪的状态,执行状态和阻塞状态,并可以在这些中进行变迁。
线程:进程中负责执行程序的一个执行控制单位,线程负责程序的执行,而一个进程允许有多个控制单位元,我们称为多线程。
1.创建线程的第一种方法:
1).继承Thread类
2).重写Thread类里面的run方法
3).创建线程的子类对象
4).调用start方法启动线程
2.创建线程的第二种方法:
1).定义类实现Runnable接口
2).实现接口里的run方法,也就是将线程执行的任务封装在run方法中
3).创建一个线程对象然后将实现Runnable接口类作为创建线程对象的构造方法的参数传入
4).调用线程对象的start方法,启动线程
线程安全:
- 多线程操作共享数据。
- 操作共享数据的代码有多条。
解决线程完全:
- 同步代码块
- 好处:解决线程安全问题
- 弊端:降低了效率,每次都要判断同步锁
- 同步代码块和同步函数
- 同步代码块的锁是任意对象,同步函数的锁是this死锁常见的情形之一,同步代码块的嵌套
线程创建:
继承方式实现线程:
(1)继承Threead类并重写run方法
public class Talk extends Thread{
public void run() {
(2)创建线程对象并调用start方法
li.start();
public class Talk extends Thread{
private String name;
public Talk(String name){
this.name = name;
}
@Override
public void run() {
for(int i=1;i<=10;i++){
System.out.printf("to %s:%d\n",name,i);
try {
Thread.sleep((int)(Math.random()*500));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("to %s:bye bye!\n",name);
}
}
测试:
public class Test {
public static void main(String[] args) {
Talk zhang = new Talk("zhang");
Talk li = new Talk("li");
zhang.start();
li.start();
}
}
结果:
to zhang:1
to li:1
to li:2
to zhang:2
to li:3
to zhang:3
to zhang:4
to li:4
to zhang:5
to li:5
to zhang:6
to li:6
接口方式实现线程:
- 实现Runnable接口继承Thread类并实现run方法
public class Demo implements Runnable {
- 创建实现了Runnable接口类的实例
Talk1 zhang = new Talk1("zhang");
- 通过传递实例创建线程对象并调用start方法
Thread t1=new Thread("zhang");
t1.start();
线程协作:
wait:使当前线程进入阻塞状态,相当于P操作;
notify:唤醒此同步锁上阻塞的第一个线程,相当于V操作;
notifyAll:唤醒此同步锁上阻塞的所有个线程。