Java核心技术卷I -- 第14章 多线程

本文详细介绍了Java多线程的基础知识和技术要点,包括线程的创建与启动、线程的状态与优先级、线程的中断与同步机制、锁的概念与应用、阻塞队列的使用方法、线程池的实现原理及应用场景等。此外,还探讨了Callable与Future接口的使用,以及如何通过线程池来提高程序的执行效率。
摘要由CSDN通过智能技术生成

1. Thread.sleep(long millis): 休眠制定的毫秒数。

2. 实现多线程的两种方法

    2.1 实现Runnable接口

        class BallRunnable implements Runnable {

            public void run() {  //需要try..catch来捕获异常

                try{

                    do something

                } catch (InterruptedException) {}

            }

        }

    2.2 继承Thread

        class MyThread extends Thread {

            public void run() {task code}

        }

    2.3 启动线程

        Ball b = new Ball();

        panel.add(b);

        Runnable r = new BallRunnable(b, panel);

        Thread t = new Thread(r);

        t.start();

        不要调用Thread类或者Runnable对象的run方法,直接调用只会在当前线程中执行任务,并不会启动新线程。

3. 中断线程

    JDK1.0 stop() 现在已经被弃用,现在使用interrupt方法来请求终止一个线程,步骤如下:

    Thread.currentThread().isInterrupted() //首先取得当前线程,然后调用isInterrupted()来判断给线程是否中断

    如果一个线程被阻塞,而调用isInterrupted() ,将会产生InterruptedException异常

    void interrupt(): 发送一个中断给一个线程,这个线程的中断状态将为True,如果当前线程被sleep调用,将抛出InterruptedException异常。常在catch(InterruptedException e) {Thread().currentThread().interrupt();}

    static boolean interrupted(): 检查当前线程是否被中断,调用它将清除该线程的中断状态

    boolean isInterrupted(): 检查线程是否被终止,而不会改变中断状态的值

4. 线程状态

    New(新生)、Runnable(可运行)、Blocked(被阻塞)、Dead(死亡)

    isAlive(): 如果线程已经启动并还没有被终止,返回true

    stop(): 停止线程。方法过时

    suspend(): 挂起当前线程的执行过程。方法过时

    resume(): 恢复线程。方法过时

    join(): 等待直到指定的线程死亡

    join(long millis): 等待直到指定的线程死亡或经过制定的毫秒数

5. 线程优先级

    线程优先级和系统有密切关系

    setPriority(int newPriority): 设置线程优先级。一般有Thread.MIN_PRIORITY(值为1)、NORM_PRIORITY(值为5)、MAX_PRIORITY(值为10) 

    static void yield(): 导致当前执行线程进入让步状态,如果有优先级不低于此线程的其他线程存在,那么这些线程将被调度。

6. 守护线程

    也成为后台线程 t.setDaemon(true); 此方法必须在线程开始之前被调用

7. 线程组

    可以把类似的线程加入一个线程组来便于统一操作

    String groupName = "myGroup";

    ThreadGroup g = new ThreadGroup(groupName);

    Thread t = new Thread(g, threadName);  //把一个线程加入到g线程组中

    g.activeCount();  //查明线程组中是否有线程处于可运行状态

    g.interrupt();  //中断线程组中所有的线程

8. 未捕获异常处理器

    线程run方法不能抛出任何被检查的异常,所以需要对一个线程安装一个处理器

    setDefaultUncaughtExceptionHandler()设置默认处理器,如果不设置,则为null

9. 同步

    两种方式,一种同步锁,一种使用Synchronized

    9.1 锁对象 - 显示锁

        private Lock bankLock = new ReentrantLock();

        bankLock.lock();

        try {do something;}

        finally {bankLock.unlock();}

    9.2 条件对象

        一个线程进入临界区,发现必须等待满足某个条件才能执行,那么就需要使用一个条件对象来实现。

        class Bank {

            private Condition sufficentFunds;    //定义条件对象

            public Bank() {

                sufficentFunds = bankLock.newConditon();    //从ReentrantLock对象中New一个Condition对象

            }

            public void transfer(int from, int to, int amount) {

                bankLock.lock();     //开始锁对象

                try {

                    while (acconts[from] < amount)

                        sufficentFunds.await();    //如果不满足条件,就进入阻塞状态

                    // transfer funds

                    sufficentFunds.signalAll();    //解除所有线程的阻塞状态

                }

                finally {bankLock.unlock();}

            }

        }

        await(): 等价于wait(),线程进入阻塞状态,当锁可获得,线程不能马上解除,直到另外一个线程调用同一条件上的signalAll方法。

        signalAll(): 等价于notifyAll(),解除阻塞状态,但是线程不会马上执行,还需要竞争锁。

        signal(): 等价于notify(),随机解除等待某个线程的阻塞状态。

    9.3 Synchronized     

        同步方法: Synchronized - 隐式锁

        同步块: 对单独代码块进行Synchronized

        同步实例域: volatile

            public boolean isDone() {return done;}

            private volatile boolean done;

10. 锁

    10.1 死锁

    10.2 公平锁

        Lock fairLock = new ReentrantLock(true);

    10.3 锁测试

        myLock.tryLock(): 尝试获得锁但不会发生阻塞,成功返回true

    10.4 读/写锁

        private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

        private Lock readLock = rwl.readLock();    //得到一个读操作可公用锁,排斥所有写操作

        private Lock writeLock = rwl.writeLock();    //得到一个写锁,排斥其他的读写操作

11. 阻塞队列

    11.1 4种阻塞队列

        ArrayBlockingQueue(int capacity)和ArrayBlockingQueue(int capacity, boolean fair): 制定容量和公平性设置的阻塞队列,用来循环数组。

        LinkedBlockingQueue()或LinkedBlockingQueue(int capacity): 构建一个无边界或者有容量的阻塞队列,由链表实现。

        DelayQueue(): 包含Delayed元素的无界的阻塞时间有限的阻塞队列

        Delayed.getDelay(TimeUnit unit): 得到该对象的延迟

        PriorityBlockingQueue(): 阻塞优先级队列

    11.2 队列方法

        add: 添加一个元素,队列满则抛出异常

        offer:添加一个元素,如果队列满返回false

        put: 添加一个元素,队列满则阻塞

        remove: 移除并返回队列头部的元素,队列空抛异常

        poll: 移除并返回队列头部的元素,队列空返回null

        take: 移除并返回队列头部的元素,队列空则阻塞

        element: 返回队列头部的元素,队列空抛异常

        peek: 返回队列头部的元素,队列空返回null

12. 线程安全的集合

    java.uti.concurrent提供两个集合: ConcurrentLinkedQueue和ConcurrentHashMap   

    ConcurrentHashMap.putIfAbsent(K key, V value): 将给定值和键联系起来

    ConcurrentHashMap.remove(K key, V value): 移除

    ConcurrentHashMap.replace(K key, V oldValue, V newValue): 新的值相关联

13. Callable和Future

    13.1 Callable相当于Runnable,但是有返回值

        class Counter implements Callable<Integer> {public Integer call()}    //定义Callable

    13.2 Future用来保存返回的结果

        Counter count = new Counter();

        FutureTask<Integer> task = new FutureTask(count);

        Thread t = new Thread(task);

        t.start(); 

        get(): 获取结果

        cancel(boolean mayInterrupt): 尝试取消任务运行,如果线程开始且mayInterrupt为true,那么被中断

        isCancelled(): 如果任务在完成之前被取消,返回true

        isDone(): 任务是否结束

14. 线程池 - 执行器

    14.1 线程池的使用

        newCachedThreadPool: 创建线程池,如果池中有空闲线程,则使用空闲线程,否则创建新线程

        newFixedThreadPool: 包含固定数量线程

        newSingleThreadExecutor: 只有一个线程的池,顺序执行

        以上3种,实现了ExecutorService接口。

        1. 调用Executors类中静态的newCachedThreadPool或newFixedThreadPool方法

            ExecutorService pool = Executors.newCachedThreadPool();

        2. 调用submit来提交一个Runnable或Callable对象

            MatchCounter counter = new MatchCounter(new File(directory), keyword, pool);    //MatchCounter是实现了Callable<Integer>

            Future<Integer> result = pool.submit(counter);    //提交返回的Callable对象

        3. 如果希望取消任务或者保存结果,那么就需要保存好Future对象

            result.get();

        4. 当不想提交任务的时候调用shutdown

            pool.shutdown();

        5. 得到线程池容量

            int ((ThreadPoolExecutor)pool).getLargestSize();

    14.2 预订执行

        newScheduledThreadPool: 为预定执行而构建的固定线程池

        newSingleThreadScheduledExcutor: 为预定执行而构建的单线程“池”

        以上2种,实现了ScheduledExecutorService接口

    14.3 控制线程组 - 把所有任务集中起来处理

        ArrayList<Callable<Integer>> tasks = ...;

        List<Future<Integer>> results = executor.invokeAll(tasks);

15. 同步器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值