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);
        }
    }
}
相关推荐
云烟成雨TD1 天前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
Wenweno0o1 天前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
小O的算法实验室1 天前
2026年ASOC,基于深度强化学习的无人机三维复杂环境分层自适应导航规划方法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
于慨1 天前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
swg3213211 天前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
gelald1 天前
SpringBoot - 自动配置原理
java·spring boot·后端
殷紫川1 天前
深入理解 AQS:从架构到实现,解锁 Java 并发编程的核心密钥
java
一轮弯弯的明月1 天前
贝尔数求集合划分方案总数
java·笔记·蓝桥杯·学习心得
chenjingming6661 天前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
殷紫川1 天前
深入拆解 Java volatile:从内存屏障到无锁编程的实战指南
java