本文主要内容:
(1)线程安全问题
(2)synchronized关键字
(3)join方法
(4)sleep方法与wait方法的区别
1.解决线程安全问题
让仓库对象被线程访问的时候,仓库对象被锁定,仓库对象只能被一个线程访问,其他线程处于等待状态。
public class House {
private ArrayList<String> list = new ArrayList<>();
//向集合中添加元素的方法
public synchronized void add(){
if(list.size()<20){
list.add("a");
}else {
try {
this.notifyAll();
this.wait();//仓库调用wait(),不是仓库对象等待,而是调用仓库生产者线程进入等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//从集合中取元素
public synchronized void get(){
if(list.size()>0){
list.remove(0);
}else {
try {
this.notifyAll();
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//Producer、Customer、TestMain类和上述一样
//运行不会产生异常,线程安全
2.特征修饰符:synchronized
同步的,一个时间点只有一个线程访问
(2-1)将synchronized关键字放在方法的结构上
public synchronized void get(){
//锁定的是调用方法时的那个对象
}
(2-2)将synchronized关键字放在方法(构造方法、块)的内部
public void get(){
synchronized(对象){
......
}
}
3.通过上述的生产消费者模型总结
(1)利用线程安全锁,特征修饰符synchronized,两种不同的写法,锁定的是对象
(2)利用方法控制线程状态来回切换方法如下:
wait(),notify(),notifyAll(),这些方法都是Object类中的方法
(3)Thread类中的方法
sleep(),setPriority();getPriority(),设置或获取线程的优先级,数字越高优先级越高,更加容易获取CPU分配的资源碎片
4.笔试题
(1)线程的几种状态

(2)sleep与wait方法的区别
sleep():它是Thread类中的静态方法,可以直接用类调用,需要用对象调用方法,唤醒不需要别人,不会释放锁
wait():他是Object类的方法,需要用对象来调用方法,访问对象的其他线程等待,需要其他对象调用notify唤醒,等待后会释放锁
5.比较重要的方法(Thead类中的join方法)
(1)设计一个模型,有两个线程,将two线程加入one里面
(2)设计模型时,two线程在one的run里面创建,保证两个有先后顺序
(3)two.join
public class ThreadOne extends Thread{
public void run(){
System.out.println("thread one start");
ThreadTwo two = new ThreadTwo();
two.start();
try {
two.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread one end");
}
}
public class ThreadTwo extends Thread {
public void run(){
System.out.println("thread two start");
System.out.println("thraed two end");
}
}
public class Test {
public static void main(String[] args) {
ThreadOne one = new ThreadOne();
one.start();
}
}
//运行结果
thread one start
thread two start
thraed two end
thread one end
(4)在写一个如下模型,在建立一个ThreadThree,one开始启动(启动后睡眠5000s),two考试启动(加入到one中2000s),three开始启动(启动后睡眠10000s),two开始加入到one中,2000s后one想将two从自己的线程中删除,但是two对象又被three对象锁定了(10000s),所有one只能等待three将two对象释放后,才能踢掉。
public class ThreadOne extends Thread{
public void run(){
System.out.println("thread one start");
ThreadTwo two = new ThreadTwo();
two.start();
try {
two.join(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread one end");
}
}
public class ThreadTwo extends Thread {
public void run(){
System.out.println("thread two start");
ThreadThree three = new ThreadThree(this);
three.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread two end");
}
}
public class ThreadThree extends Thread{
private ThreadTwo two;
public ThreadThree(ThreadTwo two){
this.two = two;
}
public void run(){
System.out.println("thread three start");
synchronized (two){
System.out.println("two is locked");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("two is free");
}
System.out.println("thread three end");
}
}
public class Test {
public static void main(String[] args) {
ThreadOne one = new ThreadOne();
ThreadTwo two = new ThreadTwo();
ThreadThree three = new ThreadThree(two);
one.start();
}
}
//运行结果
thread one start
thread two start
thread three start
two is locked
thread two end
two is free
thread three end
thread one end