java基础-多线程练习

练习一:

复制代码
package Day16_thread;

public class Ticket extends Thread {

    static int ticket=0;
    @Override
    public void run() {
        //写循环
        //同步代码块
        //判断共享数据是否到了末尾,到了末尾会怎么样
        //判断共享数据是否到了末尾,如果没有到末尾会怎么样
        while(true){
            synchronized(Ticket.class){
                if(ticket>=1000){
                    break;
                }else {
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    ticket++;
                    System.out.println(this.getName()+"正在卖第"+ticket+"张票");
                }
            }
        }
    }
}
复制代码
package Day16_thread;

public class ThreadQuestion1 {
    public static void main(String[] args) {
        //
        Ticket ticket1 = new Ticket();
        Ticket ticket2 = new Ticket();
        Ticket ticket3 = new Ticket();
        ticket1.setName("窗口1");
        ticket2.setName("窗口2");
        ticket3.setName("窗口3");

        ticket1.start();
        ticket2.start();
        ticket3.start();

    }
}

练习二:

复制代码
package Day16_thread;

public class gift extends Thread{

    static int giftNumber=100;
    @Override
    public void run() {
        //写循环
        //同步代码块
        //判断共享数据是否到了末尾,到了末尾会怎么样
        //判断共享数据是否到了末尾,没有到末尾会怎么样
        while(true){
            synchronized (gift.class){
                if(giftNumber<10){
                    break;
                }else {
                    giftNumber--;
                    System.out.println(this.getName()+"正在发放礼物,剩余礼物数量"+giftNumber);
                }
            }
        }
    }
}
复制代码
package Day16_thread;

public class ThreadQuestion2 {
    public static void main(String[] args) {
        //创建线程对象
        gift g1 = new gift();
        gift g2 = new gift();

        g1.setName("线程1");
        g2.setName("线程2");

        g1.start();
        g2.start();
    }
}

练习三:

复制代码
package Day16_thread;

public class OddNumber extends Thread {
    static int i = 1;

    @Override
    public void run() {
        //写循环
        //同步代码块
        //判断共享数据是否到了末尾,到了末尾会怎么样
        //判断共享数据是否到了末尾,如果没有到末尾会怎么样
        while (true) {
            synchronized (OddNumber.class) {
                if(i<100){
                    if(i%2==0){
                        i++;
                    }else {
                        System.out.println(this.getName()+"奇数为:"+i);
                        i++;
                    }
                }else  {
                    break;
                }
            }
        }
    }
}
复制代码
package Day16_thread;

public class ThreadQuestion3 {
    public static void main(String[] args) {
        //创建线程对象
        OddNumber n1 = new OddNumber();
        OddNumber n2 = new OddNumber();

        n1.setName("线程1");
        n2.setName("线程2");

        n1.start();
        n2.start();


    }
}

练习四:

复制代码
package Day16_thread;

import java.util.Random;

public class RedEnvelope extends Thread {
    static double money=100;
    static int count=3;
    //最小红包金额
    static final double MIN=0.01;
    @Override
    public void run() {
        //同步代码块
        //判断共享数据是否到了末尾,已经到末尾
        //判断共享数据是否到了末尾,没有到末尾
        synchronized (RedEnvelope.class) {
            if(count==0){
                //共享数据到了末尾,就没有抢到红包
                System.out.println(this.getName()+"没有抢到红包");
            }else {
                //共享数据没有到末尾,开始抢红包
                //需要注意不能直接随机,需要判断现在红包已经被抢了多少个
                double price=0;//定义每次抽奖的金额
                if(count==1){
                    //表示此时是最后一个红包,就不用随机了
                    price=money;//最后一次红包,就把钱全部给price
                }else{
                    //这里就要随机一个金额
                    Random random=new Random();
                    double bounds = money - (3 - 1) * 0.01;
                    price=random.nextDouble(bounds);
                    if(price<MIN){
                        price=MIN;
                    }
                    //修改money的金额,需要把money减去中奖的金额
                    money=money-price;
                }
                //抽奖完成
                count--;
                System.out.println(this.getName()+"抢到了"+price+"元");
            }
        }

    }
}
复制代码
package Day16_thread;

public class ThreadQuestion4 {
    public static void main(String[] args) {
        //创建线程对象
        RedEnvelope r1 = new RedEnvelope();
        RedEnvelope r2 = new RedEnvelope();
        RedEnvelope r3 = new RedEnvelope();
        RedEnvelope r4 = new RedEnvelope();
        RedEnvelope r5 = new RedEnvelope();

        r1.setName("线程1");
        r2.setName("线程2");
        r3.setName("线程3");
        r4.setName("线程4");
        r5.setName("线程5");

        r1.start();
        r2.start();
        r3.start();
        r4.start();
        r5.start();
    }
}

练习五:

复制代码
package Day16_thread;

import java.util.ArrayList;
import java.util.Random;

public class LotteryPool extends Thread{

    //定义一个集合,用来存储奖池
    //巧思:为啥要创建一个构造方法,因为这里可以保证每个线程
    //执行的是同一个集合
    ArrayList<Integer> list;
    public LotteryPool(ArrayList<Integer> list){
        this.list=list;
    }
    @Override
    public void run(){
        //套路:
        //循环
        //同步代码块
        //判断共享数据是否到了末尾,到了末尾
        //判断共享数据是否到了末尾,没有到末尾
        while(true){
            synchronized (LotteryPool.class){
               if(list.size()==0){
                   break;
               } else {
                   //生成随机数,抽奖
                   Random random = new Random();
                   int i = random.nextInt(list.size());
                   Integer result = list.get(i);
                   System.out.println(this.getName()+"产生了一个"+result+"元大奖");
                   //抽中奖励就把奖池中该奖项去掉
                   list.remove(result);
               }
            }
        }
    }
}
复制代码
package Day16_thread;

import java.util.ArrayList;
import java.util.Collections;

public class ThreadQuestion5 {
    public static void main(String[] args) {
        //创建集合
        ArrayList<Integer> list=new ArrayList<Integer>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,
                2,80,300,700);

        LotteryPool L1 = new LotteryPool(list);
        LotteryPool L2 = new LotteryPool(list);

        L1.setName("抽奖箱1");
        L2.setName("抽奖箱2");

        L1.start();
        L2.start();
    }
}

练习六:

复制代码
package Day16_thread;

import java.util.ArrayList;
import java.util.Random;

public class LotteryPool extends Thread{

    //定义一个集合,用来存储奖池
    //巧思:为啥要创建一个构造方法,因为这里可以保证每个线程
    //执行的是同一个集合
    ArrayList<Integer> list;
    public LotteryPool(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 (LotteryPool.class){
               if(list.size()==0){
                   //这里表示抽奖结束了
                   if(this.getName().equals("抽奖箱1")){
                       int list1max = getMax(list1);
                       int list1sum = getSum(list1);
                           System.out.println("在本次抽奖中"+this.getName()+"总共产生了"+list1.size()+"个奖项");
                           System.out.println("分别为:"+list1+","+"最高奖项为"+list1max+","+"总计额为"+list1sum);


                   } else if (this.getName().equals("抽奖箱2")) {
                       int list2max = getMax(list2);
                       int list2sum = getSum(list2);
                           System.out.println("在本次抽奖中"+this.getName()+"总共产生了"+list2.size()+"个奖项");
                           System.out.println("分别为:"+list2+","+"最高奖项为"+list2max+","+"总计额为"+list2sum);
                   }
                   break;
               } else {
                   //生成随机数,抽奖
                   Random random = new Random();
                   int i = random.nextInt(list.size());
                   Integer result = list.get(i);
                   if(this.getName().equals("抽奖箱1")){
                       list1.add(result);
                   } else if (this.getName().equals("抽奖箱2")) {
                       list2.add(result);
                   }
                   //抽中奖励就把奖池中该奖项去掉
                   list.remove(result);
               }
            }
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    //获取集合中的最大值和求和
    public static int getMax(ArrayList<Integer> list){
        int max=list.get(0);
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i)>max){
                max=list.get(i);
            }
        }
        return max;
    }
    public static int getSum(ArrayList<Integer> list){
        int sum=0;
        for (int i = 0; i < list.size(); i++) {
            sum+=list.get(i);
        }
        return sum;
    }
}
复制代码
package Day16_thread;

import java.util.ArrayList;
import java.util.Collections;

public class ThreadQuestion5 {
    public static void main(String[] args) {
        //创建集合
        ArrayList<Integer> list=new ArrayList<Integer>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,
                2,80,300,700);

        LotteryPool L1 = new LotteryPool(list);
        LotteryPool L2 = new LotteryPool(list);

        L1.setName("抽奖箱1");
        L2.setName("抽奖箱2");

        L1.start();
        L2.start();
    }
}

上面的写法是有点弊端的,如果抽奖箱有很多,就需要创建多个集合,可以利用线程栈的方式来改写

复制代码
package Day16_thread;

import java.util.ArrayList;
import java.util.Random;

public class LotteryPool extends Thread{

    //定义一个集合,用来存储奖池
    //巧思:为啥要创建一个构造方法,因为这里可以保证每个线程
    //执行的是同一个集合
    ArrayList<Integer> list;
    public LotteryPool(ArrayList<Integer> list){
        this.list=list;
    }

    @Override
    public void run(){
        //套路:
        //循环
        //同步代码块
        //判断共享数据是否到了末尾,到了末尾
        //判断共享数据是否到了末尾,没有到末尾
        //利用线程栈来改写
        ArrayList<Integer> boxList=new ArrayList<>();
        while(true){
            synchronized (LotteryPool.class){
               if(list.size()==0){
                   //这里表示抽奖结束了
                   System.out.println("在本次抽奖中"+this.getName()+"总共产生了"+boxList.size()+"个奖项");
                   System.out.println("分别是:"+boxList+"最高奖金为"+getMax(boxList)+"总计额为"+getSum(boxList));
                   break;
               } else {
                   //生成随机数,抽奖
                   Random random = new Random();
                   int i = random.nextInt(list.size());
                   Integer result = list.get(i);
                   boxList.add(result);
                   //抽中奖励就把奖池中该奖项去掉
                   list.remove(result);
               }
            }
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    //获取集合中的最大值和求和
    public static int getMax(ArrayList<Integer> list){
        int max=list.get(0);
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i)>max){
                max=list.get(i);
            }
        }
        return max;
    }
    public static int getSum(ArrayList<Integer> list){
        int sum=0;
        for (int i = 0; i < list.size(); i++) {
            sum+=list.get(i);
        }
        return sum;
    }
}

效果是一样的:

练习七(多线程的比较):

复制代码
package Day16_thread;

import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Callable;

public class LotterPoolCompare implements Callable<Integer> {

    //创建集合用来定义构造方法,放奖池中的奖项
    ArrayList<Integer> list;
    public LotterPoolCompare(ArrayList<Integer> list){
        this.list=list;
    }
    @Override
    public Integer call() throws Exception {
        //创建线程栈来存储不同线程的数据
        ArrayList<Integer> boxList=new ArrayList<>();
        while(true){
            synchronized (LotterPoolCompare.class){
                if(list.size()==0){
                    //这里表示抽奖结束了
                    System.out.println("在本次抽奖中"+Thread.currentThread().getName()+"总共产生了"+boxList.size()+"个奖项");
                    System.out.println("分别是:"+boxList+"最高奖金为"+getMax(boxList)+"总计额为"+getSum(boxList));
                    break;
                }else{
                    //随机抽奖
                    Random random = new Random();
                    int i = random.nextInt(list.size());
                    Integer result = list.get(i);
                    boxList.add(result);
                    //抽中奖之后,就把该奖项从集合中去掉
                    list.remove(result);
                }
            }
            //为了让每个线程抽中的数据更均匀
            Thread.sleep(10);
        }
        //循环结束之后,返回抽奖箱中的最大值
        int max = getMax(boxList);
        return max;
    }
    public static int getMax(ArrayList<Integer> list){
        int max=list.get(0);
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i)>max){
                max=list.get(i);
            }
        }
        return max;
    }
    public static int getSum(ArrayList<Integer> list){
        int sum=0;
        for (int i = 0; i < list.size(); i++) {
            sum+=list.get(i);
        }
        return sum;
    }
}
复制代码
package Day16_thread;

import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadQuestion6 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        ArrayList<Integer> list=new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,
                2,80,300,700);
        LotterPoolCompare L = new LotterPoolCompare(list);

        //创建多线程的管理对象
        FutureTask<Integer> f1=new FutureTask<Integer>(L);
        FutureTask<Integer> f2=new FutureTask<Integer>(L);

        Thread t1 = new Thread(f1);
        Thread t2 = new Thread(f2);

        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");

        t1.start();
        t2.start();
        //利用FutureTask得到线程运行的结果
        Integer f1Max = f1.get();
        Integer f2Max = f2.get();
        if (f1Max > f2Max) {
            System.out.println("抽奖箱1中产生了最大奖项:"+f1Max);
        }else {
            System.out.println("抽奖箱2中产生了最大奖项:"+f2Max);
        }
    }
}
相关推荐
cur1es1 小时前
【JVM类加载&双亲委派模型&垃圾回收机制】
java·jvm·gc·垃圾回收·类加载·双亲委派模型
Mr.朱鹏1 小时前
JVM-GC垃圾回收案例
java·jvm·spring boot·算法·spring·spring cloud·java-ee
焦糖玛奇朵婷2 小时前
实测扭蛋机小程序:开发简单,互动有趣
java·大数据·程序人生·小程序·软件需求
Nan_Shu_6142 小时前
学习: 尚硅谷Java项目之小谷充电宝(3)
java·后端·学习
WJSKad12352 小时前
【DepthPro】实战教程:单目深度估计算法详解与应用
算法
wzqllwy2 小时前
8 大经典排序算法(Java 实现):原理 + Demo + 核心分析
java·算法·排序算法
智能工业品检测-奇妙智能2 小时前
AIFlowy如何实现与现有Spring Boot项目的无缝集成?
java·spring boot·后端
We་ct2 小时前
LeetCode 77. 组合:DFS回溯+剪枝,高效求解组合问题
开发语言·前端·算法·leetcode·typescript·深度优先·剪枝
從南走到北2 小时前
JAVA无人共享无人健身房物联网结合系统源码支持小程序+公众号+APP+H5
java·物联网·小程序
格林威2 小时前
工业相机图像高速存储(C#版):内存映射文件方法,附Basler相机C#实战代码!
开发语言·人工智能·数码相机·c#·机器视觉·工业相机·堡盟相机