天天看点

线程安全与synchronized关键字

本文主要内容:

(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)线程的几种状态

线程安全与synchronized关键字

(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
           

继续阅读