スレッド(下)-スレッド通信&&消費者の問題

スレッド通信

複数のスレッドが相互にチェックし、相互に実行をスケジュールするということです

wait();スレッドを待機させ、ブロッキング状態に入ると、自動的にウェイクアップしません

notify();待機中のスレッドをウェイクアップします。複数ある場合は、優先度の高いスレッドをウェイクアップします。

notifyAll();待機中のすべてのスレッドをウェイクアップします

ケース:1〜100の数字を交互に印刷する

1.ロックを使用してRunnableメソッドを実装します

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class PrintNum implements Runnable {
    
    

    static int num = 0;
    static Lock lock = new ReentrantLock();
    static Condition con = lock.newCondition();

    @Override
    public void run() {
    
    
        while (true) {
    
    
            try {
    
    
                lock.lock();
                con.signal();//唤醒线程
                num++;
                if (num <= 100) {
    
    
                    System.out.println(Thread.currentThread().getName() + ":" + num);
                } else {
    
    
                    lock.unlock();
                    break;
                }
                con.await();//线程等待,并释放锁
                lock.unlock();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
                lock.unlock();
            }
        }
    }
}

テストクラス

public class Test {
    
    
    public static void main(String[] args) {
    
    
        PrintNum p =new PrintNum();
        Thread p1 = new Thread(p);
        Thread p2 = new Thread(p);
        p1.start();
        p2.start();
    }
}

2. Runnableを実装する方法、同期を使用して同期コードブロックを装飾する

public class PrintNum implements Runnable{
    
    

    static int num=0;
    @Override
    public void run() {
    
    
        while (true){
    
    
            synchronized (this){
    
    //implements Runnable 情况下,this只有一个,this可以充当锁
                this.notify();//唤醒等待线程 使用锁对象来调用notify(),wait();
                if (num<=100){
    
    
                    System.out.println(Thread.currentThread().getName()+":"+num);
                    num++;
                }else{
    
    
                    break;
                }
                try {
    
    
                    this.wait();//线程等待,并释放锁
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

テストクラス

public class Test {
    
    
    public static void main(String[] args) {
    
    
        PrintNum p =new PrintNum();
        Thread p1 = new Thread(p);
        Thread p2 = new Thread(p);
        p1.start();
        p2.start();
    }
}

3. Threadクラスのメソッドを継承し、同期を使用して同期コードブロックを装飾します

public class PrintNum extends Thread {
    
    

    static int num = 0;
    static Object obj =new Object();//继承Thread方式,由于创建了多个对象,需要自己创建一个唯一的对象,充当锁
    @Override
    public void run() {
    
    
        while (true) {
    
    
            synchronized (obj) {
    
    
                obj.notify();
                if (num <= 100) {
    
    
                    System.out.println(Thread.currentThread().getName() + ":" + num);
                    num++;
                } else {
    
    
                    break;
                }
                try {
    
    
                    obj.wait();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }
    }
}

テストクラス

public class Test {
    
    
    public static void main(String[] args) {
    
    
        PrintNum p1 = new PrintNum();
        PrintNum p2 = new PrintNum();
        p1.start();
        p2.start();
    }
}

消費者生産者問題

1.カウンタークラス、ストレージクラス

/*柜台中 存放共享数据*/
public class Counter {
    
    
    int num = 0;//初始物品数量为0

    /* 生产商品*/
    public synchronized void add() {
    
    
        if (num == 0) {
    
    
            num++;
            System.out.println("生产一个");
            this.notify();//唤醒消费者线程  this表示同一个柜台
        } else {
    
    
            try {
    
    
                this.wait();//生产者等待
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }

    /*消费商品 */
    public synchronized void sub() {
    
    
        if (num == 1) {
    
    
            num--;
            System.out.println("消费一个");
            this.notify();//唤醒生产者线程  this表示同一个柜台
        } else {
    
    
            try {
    
    
                this.wait();//消费者等待
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

2.プロデューサースレッド

public class Productor extends Thread {
    
    

    Counter c;

    public Productor(Counter c) {
    
    
        this.c = c;
    }

    @Override
    public void run() {
    
    
        while (true) {
    
    
            try {
    
    
                Thread.sleep(1000);//休眠指定的时间
                c.add();//调用add方法
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

3.コンシューマースレッド

/*消费者线程*/
public class Customer extends Thread {
    
    

    Counter c;

    public Customer(Counter c) {
    
    
        this.c = c;
    }

    @Override
    public void run() {
    
    

        while (true) {
    
    
            try {
    
    
                Thread.sleep(1000);
                c.sub();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}

4.テストクラス

public class Test {
    
    

    public static void main(String[] args) {
    
    

        Counter c = new Counter();//创建柜台对象,是生产或者和消费者
        Productor p = new Productor(c);
        Customer ct = new Customer(c);
        p.start();
        ct.start();
    }
}

jdk8の後にスレッドを作成する2つの方法

1から100までの問題を合計します

1.FutureTaskはタスクを受け入れるために使用されます

import java.util.concurrent.Callable;

public class SumNumThread implements Callable<Integer> {
    
    
    /*
    可以向外界返回一个结果
    可以抛出一个异常
     */
    @Override
    public Integer call() throws Exception {
    
    
        int sum=0;
        for (int i = 1; i <= 100;i++){
    
    
            sum+=i;
        }
        return sum;
    }
}
public class Test {
    
    
    public static void main(String[] args) {
    
    
        //创建任务
        SumNumThread sum = new SumNumThread();
        //接受任务
        FutureTask<Integer> futureTask = new FutureTask(sum);
        //创建线程
        Thread t = new Thread(futureTask);

        t.start();
        try {
    
    
            Integer val = futureTask.get();
            System.out.println(val);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }
    }
}

2.ExecutorServiceはスレッドプールを作成します

public class SumNumThread implements Callable<Integer> {
    
    
    /*
    可以向外界返回一个结果
    可以抛出一个异常
     */
    @Override
    public Integer call() throws Exception {
    
    
        int sum=0;
        System.out.println(Thread.currentThread().getName());
        for (int i = 1; i <= 100;i++){
    
    
            sum+=i;
        }
        return sum;
    }
}
public class Test {
    
    
    public static void main(String[] args) {
    
    
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        SumNumThread sumNumThread = new SumNumThread();

        //将任务交给线程池中线程执行
        //线程池中线程不够时,会释放其中的重复利用
        executorService.submit(sumNumThread);
        executorService.submit(sumNumThread);
        executorService.submit(sumNumThread);
        executorService.submit(sumNumThread);
        executorService.submit(sumNumThread);
        Future<Integer> f = executorService.submit(sumNumThread);
        try {
    
    
            System.out.println(f.get());
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }
        executorService.shutdown();
    }
}

おすすめ

転載: blog.csdn.net/XiaoFanMi/article/details/113442035