一、开启多线程的两种方法
1、继承Thread类,在子类中重写run()方法,然后直接创建该类对象用start开启线程。
class ThreadChild extends Thread {
public void run(){
//要实现的代码块
}
}
new ThreadChild().start();
new ThreadChild().start();
2、定义一个类,覆盖实现Runnable接口中的run()方法,并创建一个Thread类对象,传入Runnable接口的子类对象作为Thread构造函数的参数。最后start实现。
class ThreadDemo implements Runnable {
public void run(){
//要执行的代码
}
}
ThreadDemo d = new ThreadDemo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start();
二、线程安全问题
解决方案:加锁。就是将多条操作共享数据的线程代码封装起来, 当有线程在执行这些代码的时候, 其他线程不可以参与运算。 必须要当前线程把这些代码都执行完毕后, 其他线程才可以参与运算。
同步的好处:解决安全问题。
同步的弊端:由于每个线程都会进行判断锁的操作,故降低了程序运行效率。
2.1、同步代码块
synchronized(){
//需要被同步的代码
}
2.2、同步函数
在函数上加上synchronized修饰符。
同步函数的锁是固定的this,同步代码块的锁是任意的对象。
建议使用同步代码块。
三、线程间通信
其实就是多个线程在操作同一个资源,但是操作的动作不同。
3.1 涉及方法
1. wait():让线程池处于冻结状态,被wait的线程会被存储到线程池中。
2. notify():唤醒线程池中任何一个线程。
3. notifyAll():唤醒线程池中所有线程。
P.S.
1. 这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法。
2. 必须明确到底操作的是哪个锁上的线程。
3. wait和sleep的区别?
答:1)wait可以指定时间也可以不指定,sleep必须指定时间。
2)在同步中对CPU的执行权不同,锁的处理不同。
wait:释放执行权,释放锁
sleep:释放执行权,不释放锁。