第4章 Java并发编程的基础

2018-01-16  本文已影响0人  红袖者
线程的优先级:

线程的优先级越高,占用CPU的能力越强;

线程中断:

调用线程对象的interrupt()函数后,线程并不会立即中断,而是将线程的中断标识设为true,只有遇到阻塞函数(sleep()、wait()、join())时,才停止阻塞,抛出异常,并将中断标识重置为false
如何正确中断线程:
1.使用阻塞函数捕获中断,在异常处理中跳出任务,使线程结束运行;

class Runner implements Runnable{
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}

2.使用isInterrupted()判断线程是否处于中断状态,若是中断状态则跳出任务,使线程结束运行;

class Runner implements Runnable{
    @Override
    public void run() {
        while (true){
           if (Thread.currentThread().isInterrupted()){
               return;
           }
        }
    }
}

3.使用中断标识;

class Runner implements Runnable{
    public volatile boolean on = true;
    @Override
    public void run() {
        while (true){
           if (on == false){
               return;
           }
        }
    }
}
线程获取锁状态变化:
线程获取锁状态变化

1.运行中的线程尝试获取锁,若获取成功则继续运行,获取失败则进入同步队列;
2.notify()将等待队列的首节点加入同步队列,notifyAll()将等待队列的所有节点加入同步队列;
3.同步队列的首节点获取同步状态成功,即对应线程获取锁成功;
4.同步队列首节点的后续节点继续通过自旋来获取同步状态;

线程间通信:

多个线程相互配合完成计算任务;
通信方式:
1.使用volatile变量作为信号量;
2.使用synchronized进行锁同步;
3.使用wait()和notify()进行通信;

//线程1
synchronized(lock){
    while(条件不满足 ){
        lock.wait();
    }
    doSomething();
}
//线程2等待超时
synchronized(lock){
    while(条件不满足 || remainTime > 0){
        lock.wait(remain)
        remainTime = futureTime - notTime;
    }
}
//线程3
synchronized(lock){
    改变条件;
    lock.notify();
}

使用wait()和notify()时线程的状态变化


线程的状态变化

a.RUNNING状态的线程获取锁失败则进入BOLOCKED状态;
b.RUNNING状态的线程调用wait()方法后进入WAITING状态;
c.WAITING状态的线程被别的线程notify()后进入BLOCKED状态;
d.BLOCKED状态的线程获取锁成功后进入RUNNING状态;
4.使用并发计数器CountDownLatch阻塞线程;

public class CountDownLatchTest {
    //计数器初始值为2
    static CountDownLatch countDownLatch = new CountDownLatch(2);

    public static void main(String[] args){
        Thread thread1 = new Thread(new Runner(), "thread 1");
        Thread thread2 = new Thread(new Runner(), "thread 2");
        try {
            thread1.start();
            thread2.start();
            //main线程阻塞,直到计数器值为0时被唤醒
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main thread");
        return;
    }

    static class Runner implements Runnable{
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName());
                //计数器减一
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
数据库连接池示例:
数据库连接池
1.初始化一定数量的连接对象放入队列中;
2.多个线程并发的取出、归还conn对象;
3.通过加锁来解决并发问题;
线程池示例:
线程池

1.多个worker线程并发从job队列中获取job;
2.job队列为空时worker线程进入waiting状态,往job队列中添加job时notify()等待的线程,取出job并执行;
3.worker线程从非空的job队列中取出job,然后执行job;
缺点:不能指定job到指定的worker线程执行;

上一篇下一篇

猜你喜欢

热点阅读