多线程编程例子

本博文记录多线程编程的几个案例,包含了常见的几种多线程编程套路。

1.四个线程计算1到100的求和

1.依次调用thread.join(),主线程输出结果。注意:sum为共享变量,访问共享变量时,用synchronized同步

public class ThreadTest {
    private static Object LOCK = new Object();
    private static int sum = 0;
    public static void main(String[] args) throws InterruptedException {
        ThreadTest threadTest = new ThreadTest();
        Thread t1 = threadTest.new ThreadSum(1,25);
        Thread t2 = threadTest.new ThreadSum(26,50);
        Thread t3 = threadTest.new ThreadSum(51,75);
        Thread t4 = threadTest.new ThreadSum(76,100);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        System.out.println("totalSum: " + sum);
    }
    class ThreadSum extends Thread{
        private int begin;
        private int end;
        public ThreadSum(int begin, int end){
            this.begin = begin;
            this.end = end;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(100);//便于测试
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (LOCK){
                for(int i=begin; i<=end; ++i){
                    sum += i;
                }
                System.out.println(Thread.currentThread().getName() + ": " + sum);
            }

        }
    }
}
out:Thread-1: 950
Thread-0: 1275
Thread-3: 3475
Thread-2: 5050
totalSum: 5050

2.子线程执行完调用countdownlatch.countdown(),主线程调用countdownlatc.await() 等待子线程执行完成,输出结果。 注意:sum为共享变量,访问共享变量时,用synchronized同步

public class ThreadTest {
    private static Object LOCK = new Object();
    private static int sum = 0;
    private static CountDownLatch countDownLatch = new CountDownLatch(4);
    public static void main(String[] args) throws InterruptedException {
        ThreadTest threadTest = new ThreadTest();
        Thread t1 = threadTest.new ThreadSum(1,25);
        Thread t2 = threadTest.new ThreadSum(26,50);
        Thread t3 = threadTest.new ThreadSum(51,75);
        Thread t4 = threadTest.new ThreadSum(76,100);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        countDownLatch.await();

        System.out.println("totalSum: " + sum);
    }
    class ThreadSum extends Thread{
        private int begin;
        private int end;
        public ThreadSum(int begin, int end){
            this.begin = begin;
            this.end = end;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(100);//便于测试
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (LOCK){
                for(int i=begin; i<=end; ++i){
                    sum += i;
                }
                System.out.println(Thread.currentThread().getName() + ": " + sum);
            }
            countDownLatch.countDown();
        }
    }
}

3.线程池

public class ThreadTest {
    private static Object LOCK = new Object();
    private static int sum = 0;
    private static CountDownLatch countDownLatch = new CountDownLatch(4);
    public static void main(String[] args) throws InterruptedException {
        ThreadTest threadTest = new ThreadTest();
        ExecutorService pool = Executors.newFixedThreadPool(4);
        for(int i=1; i<=76; i+=25){
            pool.execute(threadTest.new ThreadSum(i, i+24));
        }
        countDownLatch.await();
        pool.shutdown();

        System.out.println("totalSum: " + sum);
    }
    class ThreadSum extends Thread{
        private int begin;
        private int end;
        public ThreadSum(int begin, int end){
            this.begin = begin;
            this.end = end;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(100);//便于测试
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (LOCK){
                for(int i=begin; i<=end; ++i){
                    sum += i;
                }
                System.out.println(Thread.currentThread().getName() + ": " + sum);
            }
            countDownLatch.countDown();
        }
    }
}

4.使用ExecutorService、Callable、Future实现有返回结果的线程

public class ThreadTest {
    private static List<Future> futureList = new ArrayList<>();
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ThreadTest threadTest = new ThreadTest();
        ExecutorService pool = Executors.newFixedThreadPool(4);
        for(int i=1; i<=76; i+=25){
            ThreadCallSum threadCallSum = threadTest.new ThreadCallSum(i, i+24);
            Future future = pool.submit(threadCallSum);
            futureList.add(future);
        }
        pool.shutdown();
        int sum = 0;
        for(Future<Integer> future: futureList){
            sum += future.get();
        }

        System.out.println("totalSum: " + sum);
    }
    class ThreadCallSum implements Callable<Integer>{
        private int begin;
        private int end;
        private int sum = 0;
        public ThreadCallSum(int begin, int end){
            this.begin = begin;
            this.end = end;
        }

        @Override
        public Integer call() throws InterruptedException {
            Thread.sleep(100);
            for(int i=begin; i<=end; ++i){
                sum += i;
            }
            System.out.println(Thread.currentThread().getName() + ": " + sum);
            return sum;
        }
    }
}
out:
pool-1-thread-2: 950
pool-1-thread-4: 2200
pool-1-thread-1: 325
pool-1-thread-3: 1575
totalSum: 5050

2.三个线程打印一个1-100的数组,要求P1=1,P2=2,P3=3,P1=4的形式

public class ThreadTest {
    private static volatile int count = 1;
    private static Object object = new Object();

    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        ExecutorService pool = Executors.newFixedThreadPool(3);
        while (count <= 100) {
            pool.execute(threadTest.new ThreadCnt());
        }
        pool.shutdown();
    }

    class ThreadCnt extends Thread {
        public void run() {
            if(count<=100) {
                synchronized (object) {
                    if (count % 3 == 1 && Thread.currentThread().getName().contains("thread-1")) {
                        System.out.println(Thread.currentThread().getName() + ": " + count);
                        count++;
                    } else if (count % 3 == 2 && Thread.currentThread().getName().contains("thread-2")) {
                        System.out.println(Thread.currentThread().getName() + ": " + count);
                        count++;
                    } else if (count % 3 == 0 && Thread.currentThread().getName().contains("thread-3")) {
                        System.out.println(Thread.currentThread().getName() + ": " + count);
                        count++;
                    }
                }
            }
        }
    }
}
out:
pool-1-thread-1: 1
pool-1-thread-2: 2
pool-1-thread-3: 3
pool-1-thread-1: 4
pool-1-thread-2: 5

3.java多线程(2个线程)交替打印0-100的奇偶数

用到了notify、wait机制

public class ThreadTest extends Thread{
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        Thread t1 = threadTest.new ThreadOdd();
        Thread t2 = threadTest.new ThreadEven();
        t1.start();
        t2.start();
    }
    private synchronized void print(String str ,int i){
        notify();
        System.out.println(str + ": " + i);
        try {
            if(i==100){//100次的时候要唤醒全部,否则循环结束不了
                notifyAll();
            }
            else{
                wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    class ThreadOdd extends Thread{
        public void run(){
            for(int i=1; i<=100; i+=2){
                print(Thread.currentThread().getName(), i);
            }
        }
    }
    class ThreadEven extends Thread{
        public void run(){
            for(int i=2; i<=100; i+=2){
                print(Thread.currentThread().getName(), i);
            }
        }
    }
}
out:
...
t1: 97
t2: 98
t1: 99
t2: 100

4.三个线程循环打印1-100,每个线程每次打印3个数

1.用线程池

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class ThreadTest{
    private static volatile int count = 1;
    private static volatile int threadCnt = 1;
    private static Object object = new Object();
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        ExecutorService pool = Executors.newFixedThreadPool(3);
        while(count<=100){
            pool.execute(threadTest.new ThreadCnt());
        }
        pool.shutdown();
    }
    class ThreadCnt extends Thread{
        public void print(){
            System.out.print(Thread.currentThread().getName() + ":");
            int k = 3;
            while(count<=100 && k!=0){
                System.out.print(" " + count);
                count++;
                k--;
            }
            System.out.println();
            threadCnt++;
        }

        public void run(){
            if(count<=100) {
                synchronized (object) {
                    if(count<=100) {//double-check
                        if (threadCnt % 3 == 1 && Thread.currentThread().getName().contains("thread-1")) {
                            print();
                        } else if (threadCnt % 3 == 2 && Thread.currentThread().getName().contains("thread-2")) {
                            print();
                        } else if (threadCnt % 3 == 0 && Thread.currentThread().getName().contains("thread-3")) {
                            print();
                        }
                    }
                }
            }
        }
    }

}

2.用notify、wait–>这个注释的很好,强推看代码!!

class ThreadTest{
    private static volatile int count = 1;//打印的count
    private static volatile int countC = 0;//线程计数:保证依次打印的顺序
    private static Object object = new Object();
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        Thread t1 = threadTest.new ThreadCnt(0);//每个线程分配id号,便于依次打印时与countC比较
        Thread t2 = threadTest.new ThreadCnt(1);
        Thread t3 = threadTest.new ThreadCnt(2);

        t1.setName("t1");
        t2.setName("t2");
        t3.setName("t3");
        t1.start();
        t2.start();
        t3.start();
    }
    class ThreadCnt extends Thread{//这里的ThreadCnt类前加不加static都可以,因为锁的是ThreadCnt.class!!
        private int id;
        public ThreadCnt(int id){
            this.id = id;
        }

        public void run(){
            while(count<=100){
                synchronized (object){//这里锁ThreadCnt.class、ThreadTest.class、object都可以!!
                    if(count<=100) {//double-check
                        if (countC % 3 == id) {//通过id保证线程依次打印
                            object.notifyAll();//这里的notifyAll()、wait()的object类对象必须与上面的synchronized里的对象保持一致!!
                            System.out.print(Thread.currentThread().getName() + ":");
                            int k = 3;
                            while (count <= 100 && k != 0) {
                                System.out.print(" " + count);
                                count++;
                                k--;
                            }
                            System.out.println();
                            countC++;
                        }
                        else{
                            try {
                                object.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    }

}

5.java实现生产者消费者模式

1.notify/wait实现

import java.util.LinkedList;
import java.util.Queue;

/**
 * @FileName: ProAndCus
 * @Author: braincao
 * @Date: 2019/3/21 14:39
 * @Description: java实现生产者消费者模式(notify/wait实现)
 */

public class ProAndCus {
    private Queue<Integer> queue = new LinkedList<>();
    private int queMaxLen = 10;
    private static Object object = new Object();
    private static volatile int dataCnt = 0;//生产的物品,为了测试,这里规定生产者最多能生产10个(1-10)
    public static void main(String[] args) {
        ProAndCus proAndCus = new ProAndCus();
        Thread p1 = proAndCus.new Pro();
        Thread p2 = proAndCus.new Pro();
        Thread p3 = proAndCus.new Pro();
        Thread p4 = proAndCus.new Pro();
        Thread c1 = proAndCus.new Cus();
        Thread c2 = proAndCus.new Cus();
        Thread c3 = proAndCus.new Cus();
        Thread c4 = proAndCus.new Cus();
        p1.setName("p1--");
        p2.setName("p2--");
        p3.setName("p3--");
        p4.setName("p4--");
        c1.setName("c1--");
        c2.setName("c2--");
        c3.setName("c3--");
        c4.setName("c4--");
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        c1.start();
        c2.start();
        c3.start();
        c4.start();
    }
    class Pro extends Thread{
        public void run(){
            try {
                while (dataCnt<10) {
                    Thread.sleep(100);
                    synchronized (object) {
                        if (queue.size() >= queMaxLen) {
                            object.wait();
                        }
                        if(dataCnt<10){
                            dataCnt++;
                            queue.offer(dataCnt);
                            System.out.println(Thread.currentThread().getName() + "生产:" + dataCnt);
                        }
                        object.notifyAll();
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    class Cus extends Thread{
        public void run(){
            try {
                while (true) {
                    Thread.sleep(100);
                    synchronized (object) {
                        if(queue.isEmpty()) {
                            if(dataCnt<10){
                                object.wait();
                            }
                            else{
                                break;
                            }
                        }
                        else{
                            System.out.println(Thread.currentThread().getName() + "消费:" + queue.poll());
                        }
                        object.notifyAll();
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

2.阻塞队列实现

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

//使用阻塞队列BlockingQueue解决生产者消费者
public class BlockingQueueConsumerProducer {
    private static volatile int dataCnt = 0;
    private static BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(10);
    public static void main(String[] args) {
        BlockingQueueConsumerProducer cp = new BlockingQueueConsumerProducer();
        //生产者线程
        Pro p1 = cp.new Pro();
        Pro p2 = cp.new Pro();
        p1.setName("p1");
        p2.setName("p2");
        //消费者线程
        Cus c1 = cp.new Cus();
        Cus c2 = cp.new Cus();
        Cus c3 = cp.new Cus();
        Cus c4 = cp.new Cus();
        Cus c5 = cp.new Cus();
        c1.setName("c1");
        c2.setName("c2");
        c3.setName("c3");
        c4.setName("c4");
        c5.setName("c5");
        p1.start();
        p2.start();
        c1.start();
        c2.start();
        c3.start();
        c4.start();
        c5.start();
    }
    /**
     * 消费者线程
     * @author tangzhijing
     *
     */
    class Cus extends Thread {
        public void run() {
            try {
                while (true) {
                    Thread.sleep((long) (1000 * Math.random()));
                    if(!blockingQueue.isEmpty()){
                        System.out.println(Thread.currentThread().getName() + "消费了:" + blockingQueue.poll());
                    }
                }
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 生产者线程
     * @author tangzhijing
     *
     */
    class Pro extends Thread{
        public void run() {
            try {
                while (true) {
                    Thread.sleep((long) (1000 * Math.random()));
                    dataCnt++;
                    blockingQueue.offer(dataCnt);
                    System.out.println(Thread.currentThread().getName() + "生产了:" + dataCnt);
                }
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

6.猴子偷桃抢着进行

一个拿2个,一个拿3个,共有9个

public class Apple {
    public static volatile int clientTotal = 9;//共有9个苹果

    //同时并发执行的线程数:两个猴子各一个线程
    public static void main(String[] args){

        Thread monkeyOne = new Thread(new Runnable() {
            @Override
            public void run() {
                while(clientTotal>=2){
                    synchronized (Apple.class) {
                        if (clientTotal >= 2) {//double-check
                            clientTotal -= 2;
                            System.out.println("A猴子拿了2个,还剩:" + clientTotal + "个");
                        }
                    }
                    try {
                        Thread.sleep(100);//为了测试期间,这里加个sleep
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread monkeyTwo = new Thread(new Runnable() {
            @Override
            public void run() {
                while(clientTotal>=3){
                    synchronized (Apple.class) {
                        if (clientTotal >= 3) {
                            clientTotal -= 3;
                            System.out.println("B猴子拿了3个,还剩:" + clientTotal + "个");
                        }
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        monkeyOne.start();
        monkeyTwo.start();

    }
}

6.猴子偷桃交替进行

public class Apple {

    public static volatile int clientTotal = 9;//共有9个苹果
    public static Object object = new Object();

    //同时并发执行的线程数:两个猴子各一个线程
    public static void main(String[] args){
        Apple apple = new Apple();
        Thread t1 = apple.new ThreadMOne();
        Thread t2 = apple.new ThreadMTwo();
        t1.start();
        t2.start();
    }
    class ThreadMOne extends Thread{
        public void run(){
            try {
                while(clientTotal>=2){
                    Thread.sleep(100);
                    synchronized (object) {
                        object.notify();
                        if(clientTotal<2){
                            break;
                        }
                        clientTotal -= 2;
                        System.out.println("A猴子拿了2个,还剩:" + clientTotal + "个");
                        if(clientTotal<3){
                            break;
                        }
                        object.wait();
                    }
                }
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    }


    class ThreadMTwo extends Thread{
        public void run(){
            try {
                while(clientTotal>=3){
                    Thread.sleep(100);
                    synchronized (object) {
                        object.notify();
                        if(clientTotal<3){
                            break;
                        }
                        clientTotal -= 3;
                        System.out.println("B猴子拿了3个,还剩:" + clientTotal + "个");
                        if(clientTotal<3){
                            break;
                        }
                        object.wait();
                    }
                }
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
out:
A猴子拿了2个,还剩:7个
B猴子拿了3个,还剩:4个
A猴子拿了2个,还剩:2个

欢迎转载,欢迎错误指正与技术交流,欢迎交友谈心

文章标题:多线程编程例子

文章字数:2.4k

本文作者:Brain Cao

发布时间:2019-10-01, 19:00:08

最后更新:2020-02-27, 19:04:06

原始链接:https://braincao.cn/2019/10/01/multithread-programming-demo/

版权声明:本文为博主原创文章,遵循 BY-NC-SA 4.0 版权协议,转载请保留原文链接与作者。

目录
×

喜欢请收藏,疼爱就打赏