Java核心复习 —— 线程

线程间的协作

线程之间如何进行协作,使得多个任务可以一起解决同一个问题。

首先出一个简单的题目,需要用到A和B两个线程来完成这个任务。解法会在本节最后列出。

要求使用A,B两个线程按顺序打印1-100,A打印奇数,B打印偶数。

wait()与notify()

wait()方法的作用是,让线程一直处于等待中,在等待过程中,锁是释放的。直到notify()notifyAll()发生,才被唤醒。

wait()、notify()和notifyAll()都是Object的公有方法。为什么要这样设计?因为锁也是对象的一部分。

注意

实际上,只能在同步方法或同步代码块中调用wait()、notify()、notifyAll(),否则会抛出IllegalMonitorStateException异常,该异常是一种运行时异常

sleep()

sleep()也会让线程进入等待中,不同的是,wait()会释放锁,而sleep()不会释放锁。

题目分析

可以使用wait()notify()来解前面那题。

首先要想

①两个线程要协作完成打印的任务,那么为了防止两个线程同时打印,就应该对打印的方法加上一道synchronized锁

②那么synchronized锁应该就要用对象锁(使用同步方法或同步代码块都是可以的),而不是类锁。思考下,为什么用类锁不行?

③怎么保证顺序打印呢?A、B两个线程要轮番获得锁,也就是A先获得锁完成打印任务,紧接着下次就不能获得锁了,要由B获得,这时就可以想到让A打印完,进入等待状态,并将锁释放出来交给B,B获得锁之后,完成打印任务,让A恢复执行。B再进入等待状态。

也就是

A获得锁,执行任务 ——> A唤醒B ——> A释放锁 ,进入等待——> B获得锁,执行任务 ——> B唤醒A ——> B释放锁,进入等待 ——> A获得锁,执行任务 ——> A唤醒B ——> A、进入等待 ——> B获得锁,执行任务 ——> 依次类推…

④于是就有了 synchronized { task()、notify()、wait()}的代码思路

运行代码


public class PrintOddEven {

    //定义打印的方法
    public synchronized void print(String str,int num){
        System.out.println(str+num);
        notify();
        try {
            if(100 != num){
                wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //奇数打印线程
    class Odd implements Runnable{
        @Override
        public void run() {
            for(int i=1;i<100;i+=2){
                print("奇数:",i);
            }
        }
    }

    //偶数打印线程
    class Even implements Runnable{
        @Override
        public void run() {
            for(int i=2;i<=100;i+=2){
                print("偶数:",i);
            }
        }
    }

    public static void main(String[] args) {
        PrintOddEven p = new PrintOddEven();
        Odd odd = p.new Odd();
        Even even = p.new Even();
        new Thread(odd).start();
        new Thread(even).start();
    }
}


运行结果
在这里插入图片描述

参考文档

Java编程思想

猜你喜欢

转载自blog.csdn.net/weixin_42142408/article/details/88960707
今日推荐