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);
        }
    }
}
相关推荐
万行1 小时前
差速两轮机器人位移与航向角增量计算
人工智能·python·算法·机器人
wjs20241 小时前
《jEasyUI 树形网格添加分页》
开发语言
我是一只小青蛙8881 小时前
C++核心过渡:类与对象精讲
开发语言·c++
不知名XL1 小时前
day25 贪心算法 part03
算法·贪心算法
鹿角片ljp1 小时前
Java多线程编程:从基础到实战的完整指南
java·开发语言·后端
超级无敌大学霸2 小时前
c语言算术转换及表达式解析
c语言·开发语言
努力学习的小廉2 小时前
【QT(八)】—— 常用控件(五)
开发语言·qt
期待のcode2 小时前
Java虚拟机的垃圾回收器
java·开发语言·jvm·算法
星火开发设计2 小时前
C++ 分支结构:if-else 与 switch-case 的用法与区别
开发语言·c++·学习·算法·switch·知识·分支