并发编程002 --- 线程的基本使用

线程状态

1、OS层面

      初始状态----可运行状态-----运行状态-------阻塞状态-------终止状态

2、java语言层面

      初始状态----运行状态-------等待状态------限时等待状态-------终止状态

      java语言层面,无法区分线程是可运行还是运行(OS层面的状态)

基本使用 --- 创建、运行、休眠、让步

1、创建

继承Thread类,并重写run方法;实现Runnable接口类;创建后进入初始状态

2、运行

Thread类的start方法;进入运行态

3、休眠

sleep方法,进入阻塞态,线程休眠期间,任意线程可获得执行权,超时后,重新等待CPU调度。

4、让步

yield方法,只是让当前线程暂停,不会进入阻塞态,期间,只有相同优先级或者更高优先级的线程可获得执行权。

从源码即可看出sleep和yield的区别,sleep会抛出InterruptedException异常,而yield不会。

等待通知 --- wait、notify、notifyAll

wait、notify和notifyAll方法并不是Thread类提供的方法,而是Object类提供的方法

wait方法:使当前执行代码的线程进行等待,并且将该线程放入等待队列中,直到被其他线程通知执行,此时释放锁;

                 执行条件为:必须获取到该对象的对象级别的锁,而且wait方法必须在同步方法或者同步代码块中执行。

notify方法:通知等待队列上的线程继续执行,执行条件和wait方法相同

notifyAll方法:通知等待队列上的所有线程继续执行,执行条件和wait方法相同

典型示例为生产者、消费者模式

public class BlockingQ {
    private LinkedList<Integer> valueList = new LinkedList<>();

    private final Object lock = new Object();

    private static final int MAX_SIZE = 3;

    public void produce() {
        Integer value = new Random().nextInt();

        synchronized (lock) {
            while (this.valueList.size() >= MAX_SIZE) {
                System.out.println("Thread " + Thread.currentThread().getName() + " produce wait.");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    System.out.println("Produce interrupted!!");
                }
            }

            System.out.println("Thread " + Thread.currentThread().getName() + " produce value.");
            this.valueList.add(value);
            lock.notifyAll();
        }
    }

    public void consume() {
        synchronized (lock) {
            while (valueList.size() <= 0) {
                System.out.println("Thread " + Thread.currentThread().getName() + " consume wait.");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    System.out.println("Consume interrupted!!");
                }
            }

            System.out.println("Thread " + Thread.currentThread().getName() + " consume value.");
            valueList.remove(0);
            lock.notifyAll();
        }
    }
}

生产者:

public class Producer implements Runnable {
    private BlockingQ blockingQ;

    public Producer(BlockingQ blockingQ) {
        this.blockingQ = blockingQ;
    }

    @Override
    public void run() {
        blockingQ.produce();
    }
}

消费者:

public class Consumer implements Runnable {
    private BlockingQ blockingQ;

    public Consumer(BlockingQ blockingQ) {
        this.blockingQ = blockingQ;
    }

    @Override
    public void run() {
        blockingQ.consume();
    }
}

执行方法:

public class Main {

    public static void main(String[] args) {

        BlockingQ blockingQ = new BlockingQ();

        Producer producer = new Producer(blockingQ);
        Consumer consumer = new Consumer(blockingQ);

        // producer
        Thread thread1 = new Thread(producer);
        Thread thread2 = new Thread(producer);
        Thread thread3 = new Thread(producer);
        Thread thread4 = new Thread(producer);

        // consumer
        Thread thread5 = new Thread(consumer);
        Thread thread6 = new Thread(consumer);
        Thread thread7 = new Thread(consumer);
        Thread thread8 = new Thread(consumer);

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        thread5.start();
        thread6.start();
        thread7.start();
        thread8.start();
    }
}

执行结果:

并发编程002 --- 线程的基本使用