美文网首页
第4章 Java并发编程的基础

第4章 Java并发编程的基础

作者: 红袖者 | 来源:发表于2018-01-16 17:30 被阅读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线程执行;

    相关文章

      网友评论

          本文标题:第4章 Java并发编程的基础

          本文链接:https://www.haomeiwen.com/subject/jlydoxtx.html