java的线程通信和Callable接口,线程池创建线程

线程通信

涉及到的三个方法:
wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
notify():一旦执行此方法,就会唤醒被wait的一个线程。 如果有多个线程被wait, 就唤醒优先级高的。
notifyAll():一旦执行此方法,就会唤醒所有被wait的线程。

示例代码:

public class test{
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);
        thread1.setName("线程1");
        thread2.setName("线程2");
        thread1.start();
        thread2.start();
    }
}


class MyThread implements Runnable {
    private int number = 0;

    @Override
    public void run() {
        synchronized (this){
            while (number <= 100){
                notifyAll();
                System.out.println(Thread.currentThread().getName()+":"+number);
                number++;
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  1. wait(), notify(), notifyAll()三个方法必须使用在同步代码块或同步方法中。
  2. wait(), notify(), notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则,会出现ILlegaLMonitorStateException异常
  3. wait(), notify(), notifyALl()三个方法是定义在java. lang. object类中。

线程通信应用:生产者/消费者问题

示例代码

public class test{
    public static void main(String[] args) {
        Clerk clerk = Clerk.ReturnClerk();
        Producer producer = new Producer(clerk);
        Consumer consumer = new Consumer(clerk);
        Thread thread = new Thread(producer);
        Thread thread1 = new Thread(consumer);
        thread.start();
        thread1.start();
    }
}

class Clerk {
    int ticket = 0;
    private static ReentrantLock lock = new ReentrantLock();
    private static Clerk clerk = null;
    private final Object object = new Object();

    private Clerk() {

    }


    public static Clerk ReturnClerk() {
        if (clerk == null) {
            try {
                lock.lock();
                if (clerk == null) {
                    clerk = new Clerk();
                }
            } finally {
                lock.unlock();
                return clerk;
            }
        } else {
            return clerk;
        }
    }

    void producerMethod(){
        synchronized (object) {
            if (ticket < 20) {
                ticket++;
                System.out.println(Thread.currentThread().getName() + ':' + "正在生产第" + ticket + "张票");
                object.notify();
            }
            else{
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    void consumerMethod(){
        synchronized (object) {
            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + ':' + "正在消费第" + ticket + "张票");
                ticket--;
                object.notify();
            }
            else{
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class Producer implements Runnable{
    private Clerk clerk;
    public Producer(Clerk clerk){
        this.clerk = clerk;
    }

    @Override
    public void run() {
        while (true) {
            this.clerk.producerMethod();
        }
    }
}


class Consumer implements Runnable{
    private Clerk clerk;
    public Consumer(Clerk clerk){
            this.clerk = clerk;
    }

    @Override
    public void run() {
        while (true) {
            this.clerk.consumerMethod();
        }
    }
}

JDK5.0之后的创建线程方法

Callable接口

如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?

  1. call()可以有返回值的。
  2. call()可以抛出异常,被外面的操作捕获,获取异常的信息
  3. Callable是支持泛型的
public class test{
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        FutureTask futureTask = new FutureTask(myThread);
        new Thread(futureTask).start();
        try {
            Object sum = futureTask.get();
            System.out.println("总和为"+sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}


class MyThread implements Callable{
    int number = 0;
    @Override
    public Object call() throws Exception {
        int total = 0;
        while (number <= 100){
            if (number % 2 == 0){
                total += number;
                System.out.println(number);
            }
            number++;
        }
        return total;
    }
}

线程池

背景:经常创建和销毁、使用量特别大的资源,比如并发情况下的线程,对性能影响很大。
思路:提前创建好多个线程,放入线程酒中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。
好处:
1.提高响应速度(减少了创建新线程的时间)
2.降低资源消耗(重复利用线程池中线程,不需要每次都创建)
3.便于线程管理
JDK 5.0起提供了线程池相关API: ExecutorService 和Executors
ExecutorService:真正的线程池接口。常见子类ThreadPoolExecutor
➢void execute(Runnable command):执行任务1命令,没有返回值,一般用来执行Runnable
➢ Future submit(Callable task): 执行任务,有返回值,一 般又来执行Callable
➢void shutdown() :关闭连接池
Executors: 工具类、线程池的工厂类,用于创建并返回不同类型的线程池
➢Executors.newCachedThreadPool(): 创建一个可 根据需要创建新线程的线程池
➢Executors .newFixedThreadPool(n);创建一个可 重用固定线程数的线程池
➢Executors.newSingleThreadExecutor():创建一个 只有一-个线程的线程池
➢Executors.newScheduledThreadPool(n): 创建一个线程池, 它可安排在给定延迟后运行命令或者定期地执行。

public class test{
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        executorService.execute(new MyThread());
        executorService.execute(new MyThread1());
        executorService.shutdown();
    }
}


class MyThread implements Runnable{
    @Override
    public void run() {
        int number = 0;
        while (number <= 100){
            if (number % 2 == 0){
                System.out.println(number);
            }
            number++;
        }
    }
}

class MyThread1 implements Runnable{
    @Override
    public void run() {
        int number = 0;
        while (number <= 100){
            if (number % 2 != 0){
                System.out.println(number);
            }
            number++;
        }
    }
}

如果需要设置线程池的一些属性

public class test{
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor server = (ThreadPoolExecutor)executorService;
        server.setCorePoolSize(10);
        server.execute(new MyThread());
        server.execute(new MyThread1());
        executorService.shutdown();
    }
}


class MyThread implements Runnable{
    @Override
    public void run() {
        int number = 0;
        while (number <= 100){
            if (number % 2 == 0){
                System.out.println(number);
            }
            number++;
        }
    }
}

class MyThread1 implements Runnable{
    @Override
    public void run() {
        int number = 0;
        while (number <= 100){
            if (number % 2 != 0){
                System.out.println(number);
            }
            number++;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值