Thread类阻塞队列的用法练习

1.用两个线程分别计算1-100之间偶数的和奇数的和

给定一个很长的数组 (长度 1000w), 通过随机数的方式生成 1-100 之间的整数.

实现代码, 能够创建两个线程, 对这个数组的所有元素求和.

其中线程1 计算偶数下标元素的和, 线程2 计算奇数下标元素的和.

最终再汇总两个和, 进行相加

记录程序的执行时间.

import java.util.Random;

public class Demo5 {
    public static void main(String[] args) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        int total = 1000_0000;
        int[] a = new int[total];
        Random random = new Random();
        for (int i = 0; i < total; i++) {
            int num = random.nextInt(100)+1;
            a[i] = num;
        }
        Operation operation = new Operation();
        Thread t1 = new Thread(()->{

            for (int i = 0; i < total; i+=2) {
                operation.addEvenSum(a[i]);
            }

        });
        Thread t2 = new Thread(() ->{
            for (int i = 1; i < total; i+=2) {
                operation.addOddSum(a[i]);
            }

        });
        t1.start();
        t1.join();
        t2.start();
        t2.join();
        long endTime = System.currentTimeMillis();
        System.out.println(operation.result());
        System.out.println(endTime - startTime +"ms");
    }
    static class Operation {
        long evenSum;
        long oddSum;
        private void addEvenSum(int num){
            evenSum += num;
        }
        private void addOddSum(int num){
            oddSum += num;
        }
        public long result(){
            System.out.println("偶数的和:"+evenSum);
            System.out.println("奇数的和:"+oddSum);
            return evenSum + oddSum;
        }

    }

    }

2.请说明Thread类中run和start的区别

作用功能不同:

  1. run方法的作用是描述线程具体要执行的任务;
  2. start方法的作用是真正的去申请系统线程

运行结果不同:

  1. run方法是一个类中的普通方法,主动调用和调用普通方法一样,会顺序执行一次;
  2. start调用方法后, start方法内部会调用Java 本地方法(封装了对系统底层的调用)真正的启动线程,并执行run方法中的代码,run 方法执行完成后线程进入销毁阶段。

3. 请描述 volatile 关键字的作用

volatile关键字的作用主要有如下两个:

  1. 保证内存可见性:基于屏障指令实现,即当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。
  2. 保证有序性:禁止指令重排序。编译时 JVM 编译器遵循内存屏障的约束,运行时靠屏障指令组织指令顺序。

注意:volatile 不能保证原子性

4. 每个线程循环 1w 次,累加变量 count 的值,count 默认值为 0,注意线程安全问题。

public class Demo6 {
    public static int count = 0;
    public static void main(String[] args) throws InterruptedException {
        Object object = new Object();
        Thread t1 = new Thread(() ->{
            for (int i = 0; i < 10000; i++) {
                System.out.println("count的值"+count);
                synchronized (object){
                    count++;
                }
            }
            System.out.println("t1线程结束");
        });
        Thread t2 = new Thread(() ->{
            for (int i = 0; i < 10000; i++) {
                System.out.println("count的值"+count);
                synchronized (object){
                    count++;
                }
            }
            System.out.println("t2线程结束");
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(count);
    }
}

5. 打印ABC按照下列要求

有三个线程,分别只能打印A,B和C

要求按顺序打印ABC,打印10次

输出示例:

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC

public class Demo2 {
    public static void main(String[] args) throws InterruptedException {
        Object locker1 = new Object();
        Object locker2 = new Object();
        Object locker3 = new Object();


        Thread t1 = new Thread(() -> {
            try {

                for (int i = 0; i < 10; i++) {
                    synchronized (locker1){
                        locker1.wait();
                    }
                    System.out.print("A");
                    synchronized (locker2){
                        locker2.notify();
                    }
                }

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        });
        Thread t2 = new Thread(() ->{
            try {

                for (int i = 0; i < 10; i++) {
                    synchronized (locker2){
                        locker2.wait();
                    }
                    System.out.print("B");
                    synchronized (locker3){
                        locker3.notify();
                    }
                }

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        Thread t3  = new Thread(() ->{
            try {

                for (int i = 0; i < 10; i++) {
                    synchronized (locker3){
                        locker3.wait();
                    }
                    System.out.println("C");
                    synchronized (locker1){
                        locker1.notify();
                    }
                }

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        t1.start();
        t2.start();
        t3.start();
        Thread.sleep(1000);
        synchronized (locker1){
            locker1.notify();
        }
    }
}

6.同时启动打印线程名称

有三个线程,线程名称分别为:a,b,c。

每个线程打印自己的名称。

需要让他们同时启动,并按 c,b,a的顺序打印

public class Demo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(()->{
            System.out.print(Thread.currentThread().getName()+" ");
        },"c");

        Thread t2 = new Thread(()->{
            try {
                t1.join();
            }catch (InterruptedException e){
                throw new RuntimeException(e);
            }

            System.out.print(Thread.currentThread().getName()+" ");
        },"b");

        Thread t3= new Thread(()->{
            try {
                t2.join();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.print(Thread.currentThread().getName()+" ");
        },"a");
             t1.start();
             t2.start();
             t3.start();
    }
}

 7.按照要求写一个死锁的代码

提供:可以通过 synchronized 或者 Lock 来实现一个死锁代码。

所谓的死锁就是线程一拥有锁1,线程二拥有锁2,双方在拥有自身锁的同时尝试获取对方的锁,最终两个线程就会进入无线等待的状态,这就是死锁。

Object lock1 = new Object();
Object lock2 = new Object();

Thread t1 = new Thread(() -> {
    synchronized (lock1) {
        System.out.println(Thread.currentThread().getName() +
                ":已经获取到锁1");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (lock2) {
            System.out.println(Thread.currentThread().getName() +
                    ":获取到锁2");
        }
    }
}, "t1");
t1.start();


Thread t2 = new Thread(() -> {
    synchronized (lock2) {
        System.out.println(Thread.currentThread().getName() + ":获取到锁2");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (lock1) {
            System.out.println(Thread.currentThread().getName() + ":获取到锁1");
        }
    }
}, "t2");
t2.start();

8.阻塞队列代码编写


   class MyBlockingQueue1 {
       public String[] data = null;
       private int head = 0;
       private int tail = 0;

       MyBlockingQueue1(int capacity) {
           data = new String[capacity];
       }

       private int size = 0;

       void put(String val) throws InterruptedException {
           synchronized (this) {
               while (size == data.length) {

                   this.wait();

               }
               data[tail] = val;
               tail++;
               if (tail >= data.length) {
                   tail = 0;
               }
               size++;
               notify();
           }
       }

       String take() throws InterruptedException {
           synchronized (this) {
               while (size == 0) {

                   this.wait();
               }

               String e = data[head];
               head++;
               if (head == data.length) {
                   head = 0;
               }
               size--;
               this.notify();
               return e;

           }
       }
           public int getSize () {
               return size;
           }

       }



public class Demo4 {
    public static void main(String[] args) {
        MyBlockingQueue1 queue1 = new MyBlockingQueue1(100);

        Thread producer = new Thread(()->{
           int n = 0;
            while(true){
                try {
                    queue1.put(n+"");
                    System.out.println("生产"+n);
                    n++;
                }catch (InterruptedException e){
                    throw new RuntimeException(e);
                }

            }

        });
        Thread consumer = new Thread(()->{
            while(true){
                String n = null;
                try {
                    n =  queue1.take();
                    System.out.println("消费"+n);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        producer.start();
        consumer.start();
    }



}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值