多线程--毕向东
创建线程的两种方式:
1、继承Thread类
1.1 定义一个类继承Thread类。
1.2 重写run方法。
1.3 创建子类对象,就是创建线程对象。
1.4 调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。
class Demo extends Thread { public void run () {// 线程任务
while(true) { } } } class threadDemo1 { public static void main(String[] args) { Demo d = new Demo(); d.start(); } }
2、实现Runnable接口
2.1 定义类实现Runnable接口。
2.2 覆盖接口中的run方法。将线程任务代码定义到run方法中。
2.3 创建Thread类的对象。
2.4 将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
2.5 通用Thread类的start方法开启线程。
class Demo implements Runnable { public void run () { // 任务 } } class threadDemo2 { public static void main(String[] args) { Demo d = new Demo("Demo"); Thread t = new Thread(d); t.start(); } }
第二种方式实现Runnable接口避免了单继承的局限性,所以比较常用。
实现Runnable接口的方式,更加的符合面向对象。线程分为两部分:线程对象,线程任务。
继承Thread类:线程对象和线程任务耦合在一起。创建的Thread类的子类对象,即使线程对象,又是线程任务。
实现Runnable接口:将线程任务单独分离出来封装成对象,类型就是Runnable接口类型。Runnable接口对线程对象和线程任务进行解耦。
Thread的源码大致如下:
class Thread {
private Runnable target;
Thread(Runnable target) {
this.target = target;
}
public void run() {
if(target != null) {
target.run();
}
}
public void start() {
run();
}
}
线程状态
多线程的安全问题
安全问题的发生:
案例:售票的例子。
售票的动作需要同时执行,所以使用多线程技术。
发生了线程安全问题:出现了错误数据。 0 -1 -2
问题产生的原因:
1、多个线程在操作共享的数据。
2、线程任务操作共享数据的代码有多条(运算有多个)。
解决思路:
只要让一个线程在执行线程任务时将多条操作共享数据的代码执行完,在执行过程中,不要让其他线程参与运算。
代码体现:
Java中解决此问题通过代码块来完成。
这个代码块:同步代码块 synchronized
格式:
synchronized(对象) {
// 需要被同步的代码
}
同步的好处:
解决多线程安全问题。
同步的弊端:
降低了程序的性能。
同步的前提:
必须保证多个线程在同步中使用的是同一个锁。
解决了什么问题?
当多线程安全问题发生时,加入了同步后,问题依旧,就要考虑同步的前提有没有问题。