JavaDay18-多线程(三)

5、题目:抽奖箱。(我的实现方法)

  • 抽奖池中奖励的金额为:
  • 创建两个抽奖箱名称分别为”抽奖箱1“”抽奖箱2“
  • 随机从抽奖池中抽取元素并打印在控制台上,格式如下:
    抽奖箱1又产生了一个10元大奖
    抽奖箱1又产生了一个100元大奖
    抽奖箱2又产生了一个800元大奖
    ...
public class Question {
    public static void main(String[] args) {
        Draw draw = new Draw();
        Thread thread1 = new Thread(draw);
        Thread thread2 = new Thread(draw);
        thread1.setName("抽奖箱1");
        thread2.setName("抽奖箱2");
        thread1.start();
        thread2.start();
    }
}
import java.util.Random;
//不知道为什么这种实现方式停不下来,会一直运行????但输出结果是对的
//知道了!!count没有自增...
public class Draw implements Runnable{
    private static int[] draw= {10,5,20,50,100,500,200,800,2,80,300,700};
    private static int count;
    @Override
    public void run() {
        while (true){
            synchronized (Draw.class){
                if (count==draw.length-1){
                    break;
                }else {
                    Random random = new Random();
                    int i = random.nextInt(draw.length-1);
                    if (draw[i]!=0){
                        int price=draw[i];
                        draw[i]=0;
                        System.out.println(Thread.currentThread().getName()+"又产生了一个"+price+"元大奖");
                        count++;
                    }
                }
            }
        }
    }
}

6、题目:抽奖箱。(老师的实现方法)

  • 抽奖池中奖励的金额为:
  • 创建两个抽奖箱名称分别为”抽奖箱1“”抽奖箱2“
  • 随机从抽奖池中抽取元素并打印在控制台上,格式如下:
    抽奖箱1又产生了一个10元大奖
    抽奖箱1又产生了一个100元大奖
    抽奖箱2又产生了一个800元大奖
    ...
public class Question {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,500,200,800,2,80,300,700);
        Draw draw = new Draw(list);
        Thread thread1 = new Thread(draw);
        Thread thread2 = new Thread(draw);
        thread1.start();
        thread2.start();
    }
}
import java.util.ArrayList;
import java.util.Collections;
//用集合存储{10,5,20,50,100,500,200,800,2,80,300,700}
public class Draw implements Runnable{
    //定义变量
    ArrayList<Integer> list;
    //传递参数
    public Draw(ArrayList<Integer> list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true){
            synchronized (Draw.class){
                if (list.size()==0){
                    break;
                }else {
                    Collections.shuffle(list);//打乱顺序
                    int i= list.remove(0);//删除抽到的元素
                    System.out.println(Thread.currentThread().getName()+"又产生了一个"+i+"元大奖");
                }
            }
        }
    }
}

7、题目:抽奖箱(二)。

  • 抽奖池中奖励的金额为:
  • 创建两个抽奖箱名称分别为”抽奖箱1“”抽奖箱2“
  • 每次抽的过程中不打印,抽完一次性打印,打印格式如下:
    在此次抽奖抽奖过程中,抽奖箱1一共产生了6个奖项。
    分别为:10,5,20,100,500,800最高奖项为800,总计金额为***元
    ...
public class Question {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,500,200,800,2,80,300,700);
        Draw2 draw = new Draw2(list);
        Thread thread1 = new Thread(draw);
        Thread thread2 = new Thread(draw);
        thread1.setName("抽奖箱1");
        thread2.setName("抽奖箱2");
        thread1.start();
        thread2.start();
    }
}
import java.util.ArrayList;
import java.util.Collections;
//用集合存储{10,5,20,50,100,500,200,800,2,80,300,700}
public class Draw2 implements Runnable{
    //定义变量
    ArrayList<Integer> list;
    //传递参数
    public Draw2(ArrayList<Integer> list) {
        this.list = list;
    }
    static ArrayList<Integer> list1 = new ArrayList<>();
    static ArrayList<Integer> list2 = new ArrayList<>();
    @Override
    public void run() {
        while (true){
            synchronized (practise.question6.Draw.class){
                if (list.size()==0){
                    int max=0;
                    int count=0;
                    int sum=0;
                    if ("抽奖箱1".equals(Thread.currentThread().getName())){
                        for (Integer integer : list1) {
                            if (integer>max){
                                max=integer;
                            }
                            count++;
                            sum+=integer;
                        }
                        System.out.println("在此次抽奖抽奖过程中,抽奖箱1一共产生了"+count+"个奖项,分别是:"+list1+"最高奖项为"+max+"最高奖项为"+sum);
                    }else {
                        for (Integer integer : list2) {
                            if (integer>max){
                                max=integer;
                            }
                            count++;
                            sum+=integer;
                        }
                        System.out.println("在此次抽奖抽奖过程中,抽奖箱2一共产生了"+count+"个奖项,分别是:"+list2+"最高奖项为"+max+"最高奖项为"+sum);
                    }
                    break;
                }else {
                    Collections.shuffle(list);//打乱顺序
                    int i= list.remove(0);//删除抽到的元素
                    if ("抽奖箱1".equals(Thread.currentThread().getName())){
                        list1.add(i);
                    }else {
                        list2.add(i);
                    }
                }
            }
        }
    }
}

8、题目:抽奖箱(二)优化。

  • 抽奖池中奖励的金额为:
  • 创建两个抽奖箱名称分别为”抽奖箱1“”抽奖箱2“
  • 每次抽的过程中不打印,抽完一次性打印,打印格式如下:
    在此次抽奖抽奖过程中,抽奖箱1一共产生了6个奖项。
    分别为:10,5,20,100,500,800最高奖项为800,总计金额为***元
    ...
import java.util.ArrayList;
import java.util.Collections;
/*
内存分析:
每一条线程都会有自己的线程栈,
在本测试类中一共有三个线程栈:main、thread1、thread2
在线程栈中存放了run()方法,
和run()方法中创建的变量和集合。
创建的draw对象存放在堆中。
 */
public class Question {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,500,200,800,2,80,300,700);
        Draw3 draw = new Draw3(list);
        Thread thread1 = new Thread(draw);
        Thread thread2 = new Thread(draw);
        thread1.setName("抽奖箱1");
        thread2.setName("抽奖箱2");
        thread1.start();
        thread2.start();
    }
}
import java.util.ArrayList;
import java.util.Collections;

//用集合存储{10,5,20,50,100,500,200,800,2,80,300,700}
public class Draw3 implements Runnable{
    //定义变量
    ArrayList<Integer> list;
    //传递参数
    public Draw3(ArrayList<Integer> list) {
        this.list = list;
    }
    @Override
    public void run() {
        //线程会创建自己的list,不需要手动创建多个list
        ArrayList<Integer> list1 = new ArrayList<>();
        while (true){
            synchronized (practise.question6.Draw.class){
                if (list.size()==0){
                    /*int max=0;
                    int count=0;
                    int sum=0;
                    for (Integer integer : list1) {
                            if (integer>max){
                                max=integer;
                            }
                            count++;
                            sum+=integer;
                    }*/
                    //可以用collections中的方法
                    int max=Collections.max(list1);
                    int count=list1.size();
                    int sum=0;
                    for (Integer integer : list1) {
                        sum+=integer;
                    }
                    System.out.println("在此次抽奖抽奖过程中,"+Thread.currentThread().getName()+"一共产生了"+count+"个奖项,分别是:"+list1+"最高奖项为"+max+"最高奖项为"+sum);
                    break;
                }else {
                    Collections.shuffle(list);//打乱顺序
                    int i= list.remove(0);//删除抽到的元素
                    list1.add(i);
                }
            }
        }
    }
}

9、题目:抽奖箱(三)。

  • 抽奖池中奖励的金额为:
  • 创建两个抽奖箱名称分别为”抽奖箱1“”抽奖箱2“
  • 每次抽的过程中不打印,抽完一次性打印
  • 比较两条线程:抽奖箱产生了最大奖项,金额为**元。
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Question {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,500,200,800,2,80,300,700);
        Draw4 draw = new Draw4(list);
        FutureTask<Integer> futureTask1 = new FutureTask<>(draw);
        FutureTask<Integer> futureTask2 = new FutureTask<>(draw);
        Thread thread1 = new Thread(futureTask1);
        Thread thread2 = new Thread(futureTask2);
        thread1.setName("抽奖箱1");
        thread2.setName("抽奖箱2");
        thread1.start();
        thread2.start();
        Integer i1 = futureTask1.get();
        Integer i2 = futureTask2.get();
        if (i1>i2){
            System.out.println(thread1.getName()+"产生了最大奖项,金额为"+i1);
        }else {
            System.out.println(thread2.getName()+"产生了最大奖项,金额为"+i2);
        }
    }
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.Callable;

//用集合存储{10,5,20,50,100,500,200,800,2,80,300,700}
public class Draw4 implements Callable<Integer> {
    //定义变量
    ArrayList<Integer> list;
    //传递参数
    public Draw4(ArrayList<Integer> list) {
        this.list = list;
    }

    @Override
    public Integer call() throws Exception {
        ArrayList<Integer> list1 = new ArrayList<>();
        while (true) {
            synchronized (practise.question6.Draw.class) {
                if (list.size() == 0) {
                    break;
                } else {
                    Collections.shuffle(list);//打乱顺序
                    int i = list.remove(0);//删除抽到的元素
                    list1.add(i);
                }
            }
        }
        if (list1.size()==0){
            return 0;
        }else {
            return Collections.max(list1);
        }
    }
}

十、线程池

10.1 线程池--回收线程:

1、线程池中线程数量无上限

public static ExecutorService newCachedThreadPool()

2、线程池中线程数量人为固定上限上限

public static ExecutorService newFixedThreadPool(int nThreads)

3、线程池工具类--Executors

10.2 核心原理:

1、创建线程池后,池中是空的
2、提交任务时,池子会创建新的线程;任务执行完后,线程还给池子;下一次提交任务时,不需要创建新的线程,直接复用已有的线程即可
3、如果提交任务时线程池中没有空闲的线程,任务只能排队等待,无法创建新的线程

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolTest {
    public static void main(String[] args) {
        /*//创建线程池对象-无上限
        ExecutorService pool = Executors.newCachedThreadPool();*/
        //自定义最多只能创建3个线程
        ExecutorService pool = Executors.newFixedThreadPool(3);
        //提交任务(5条任务,会创建5个线程)
        pool.submit(new ThreadPool());
        pool.submit(new ThreadPool());
        pool.submit(new ThreadPool());
        pool.submit(new ThreadPool());
        pool.submit(new ThreadPool());
        //销毁线程池
        pool.shutdown();
    }
}
public class ThreadPool implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"----------");
    }
}

10.3 自定义线程池

ThreadPoolExecutor pool = new ThreadPoolExecutor(核心线程数,最大线程数,空闲线程最大存活时间,时间单位,任务队列,创建线程工厂,任务拒绝策略);
参数一:核心线程数--不能小于0
参数二:最大线程数--不能小于0,最大数量>=核心线程数
参数三:空闲线程最大存活时间--不能小于0
参数四:时间单位--用TimeUnit指定
参数五:任务队列--不能为null
参数六:创建线程工厂--不能为null
参数七:任务拒绝策略--不能为null
细节:核心线程数+临时线程数=最大线程数
import java.util.concurrent.*;
public class ThreadPoolTest {
    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                3,//核心线程数--不能小于0
                6,//临时线程数==3
                60,//60没有工作就会被摧毁
                TimeUnit.SECONDS,//单位:秒
                new ArrayBlockingQueue<>(3),//阻塞队列,指定队列的长度--ArrayBlockingQueue,无线长度--LinkedBlockingQueue
                Executors.defaultThreadFactory(),//创建线程工厂--底层是new Thread
                new ThreadPoolExecutor.AbortPolicy()//任务拒绝策略--AbortPolicy是ThreadPoolExecutor的内部类
        );//假如有10个任务到来时,先创建核心线程处理3个任务,后将第4-6个任务任务放在阻塞队列中排队,当阻塞队列满了时,创建临时线程执行第7-9个任务,此时还有1个任务,就用到了任务拒绝策略
        ThreadPool thread = new ThreadPool();
        pool.submit(thread);
        Thread.sleep(1000);
        pool.submit(thread);
        Thread.sleep(1000);
        pool.submit(thread);
    }
}
public class ThreadPool implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"-----");
    }
}
posted @ 2023-04-15 16:18  小园初来乍到  阅读(40)  评论(0)    收藏  举报