练习1

package lx1;

/*一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,
要求:请用多线程模拟卖票过程并打印剩余电影票的数量*/
public class MyThread extends Thread {
    static int ticket = 1000;//多个线程对象共享同一个电影票

    //第一种方式实现多线程,测试类中MyThread会创建多次,所以需要加stat
    @Override
    public void run() {
        //1.循环
        while (true) {
            //2.同步代码块
            synchronized (MyThread.class) {
                //3.判断共享数据(已经到末尾)
                if (ticket == 0) {
                    break;
                } else {
                    //4.判断共享数据(没有到末尾)
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    ticket--;
                    System.out.println(getName() + "在卖票,还剩下" + ticket + "张票!!!");
                }
            }
        }

    }
}
package lx1;

public class demo1 {
    public static void main(String[] args) {
/*
            一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,
            要求:请用多线程模拟卖票过程并打印剩余电影票的数量
        */


        //1.创建多线程
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        t1.setName("窗口1");
        t2.setName("窗口2");
        //2.启动线程
        t1.start();
        t2.start();
    }
}

练习2

package lx2;

/*
有100份礼品,两人同时发送,当剩下的礼品小于10份的时候则不再送出,
利用多线程模拟该过程并将线程的名字和礼物的剩余数量打印出来.
 */
public class MyThread extends Thread {
    static int liping = 100;

    @Override
    public void run() {
        //1.循环
        while (true) {
            //2.同步代码块
            synchronized (MyThread.class) {
                //3.判断共享数据(已经到了末尾)
                if (liping == 0) {
                    break;
                } else {
                    //4.判断共享数据(没有到末尾)
                    //当剩下的礼品小于10份的时候则不再送出
                    try {
                        Thread.sleep(00);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    if (liping < 10) {
                        break;
                    }
                    liping--;
                    System.out.println(getName() + "还剩余" + liping + "份礼品");

                }


            }
        }
    }
}
package lx2;

public class demo1 {
    public static void main(String[] args) {
          /*
            有100份礼品,两人同时发送,当剩下的礼品小于10份的时候则不再送出,
            利用多线程模拟该过程并将线程的名字和礼物的剩余数量打印出来.
        */
        //1,创建多线程对象
        MyThread t1 = new MyThread();

        MyThread t2 = new MyThread();
        t1.setName("小明");
        t2.setName("小华");
        //2.启动线程
        t1.start();
        t2.start();

    }
}

练习3

package lx3;

/*
          同时开启两个线程,共同获取1-100之间的所有数字。
          要求:将输出所有的奇数。
       */
public class MyRunable implements Runnable {
    //采用第二种方式实现多线程 不需要加上static修饰 因为创建的线程对象是MyRunable的实例对象,而实例对象是唯一的
    int number = 1;

    @Override
    public void run() {
        //1.循环
        while (true) {

            //2.同步代码块
            synchronized (MyRunable.class) {
                //3.判断共享数据(已经到末尾)
                if (number > 100) {
                    break;
                } else {
                    //4.判断共享数据(还没有到末尾)
                    if (number % 2 == 1) {
                        System.out.println(Thread.currentThread().getName() + "打印数字" + number);

                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    number++;
                }
            }
        }

    }
}
package lx3;

public class Test {
    public static void main(String[] args) {
        /*
           同时开启两个线程,共同获取1-100之间的所有数字。
           要求:将输出所有的奇数。
        */


        //创建多线程对象,表示多线程要执行的任务
        MyRunable mr = new MyRunable();
        Thread t1 = new Thread(mr);

        Thread t2 = new Thread(mr);
        t1.setName("线程1");
        t2.setName("线程2");
        //启动线程
        t1.start();
        t2.start();


    }
}

 

练习4

package lx4;

import java.util.Random;

/*
           微信中的抢红包也用到了多线程。
           假设:100块,分成了3个包,现在有5个人去抢。
           其中,红包是共享数据。
           5个人是5条线程。
           打印结果如下:
               XXX抢到了XXX元
               XXX抢到了XXX元
               XXX抢到了XXX元
               XXX没抢到
               XXX没抢到
       */
public class Mythread extends Thread {
    //共享数据
    //100块,分成了3个包
    static double money = 100;
    static int count = 3;
    //设置最小的中奖金额
    static final double MIN = 0.01;

    @Override
    public void run() {
        //同步代码块
        synchronized (Mythread.class) {
            //判断共享数据是否到了末尾(已经到了末尾)
            if (count == 0) {
                System.out.println(getName() + "没有抢到红包!");
            } else {
                /*
                不能随机随机
                现在有100元
                第一次随机从100里面随机一个金额 比如说50
                第二次随机就要从剩下来的50元里面随机  比如说30
                第三次随机就直接把剩下的的20元当做抽取到的红包即可 没必要随机了
                 */
                //判断共享数据是否到了末尾(还没有到了末尾)

                //定义一个变量,表示抽到红包的金额
                double price = 0;
                if (count == 1) {
                    //表示最后一个红包
                    //就无需随机 ,剩下的所有的钱都是中奖金额
                    price = money;
                } else {
                    //表示第一次或者第二次抽取红包(随机)
                    Random r = new Random();
                    //现在有100元  3个红包
                    //第一次最多抽取99.98 因为还剩下2个红包要抽取,最小金额是0.01元
                    //100-(3-1)*0.01=99.98
                    double bounds = money - (count - 1) * MIN;
                    price = r.nextDouble(bounds) + MIN;//不包括抽取金额为0 所以加上最小金额0.01  0.01-99.99 不包括99.99

                }
                //从money当中,去掉当前中奖的金额
                money -= price;
                //红包的个数-1
                count--;
                //本次红包的信息进行打印
                System.out.println(getName() + "抢到了" + price + "元");
            }
        }

    }
}

package lx4;

public class Test {
    public static void main(String[] args) {
         /*
            微信中的抢红包也用到了多线程。
            假设:100块,分成了3个包,现在有5个人去抢。
            其中,红包是共享数据。
            5个人是5条线程。
            打印结果如下:
            	XXX抢到了XXX元
            	XXX抢到了XXX元
            	XXX抢到了XXX元
            	XXX没抢到
            	XXX没抢到
        */
        //一次线程只能执行一次完整的run方法
        Mythread t1 = new Mythread();
        Mythread t2 = new Mythread();
        Mythread t3 = new Mythread();
        Mythread t4 = new Mythread();
        Mythread t5 = new Mythread();
        t1.setName("张三");
        t2.setName("王五");
        t3.setName("李四");
        t4.setName("赵六");
        t5.setName("小小");

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();


    }
}

练习5

package lx5;
/*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
                             每次抽出一个奖项就打印一个(随机)
            	抽奖箱1 又产生了一个 10 元大奖
            	抽奖箱1 又产生了一个 100 元大奖
            	抽奖箱1 又产生了一个 200 元大奖
            	抽奖箱1 又产生了一个 800 元大奖
            	抽奖箱2 又产生了一个 700 元大奖
            	.....
        */

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

public class MyThread extends Thread {
    //共享数据
    // 奖励的金额
    ArrayList<Integer> list;

    public MyThread(ArrayList<Integer> list) {
        this.list = list;
    }
/*
我们采用随机抽一个删一个的方法
 */

    @Override
    public void run() {
        //1.循环
        while (true) {

            //同步代码块
            synchronized (MyThread.class) {
                //判断共享数据是否到了末尾(到了末尾)
                if (list.size() == 0) {
                    break;
                } else {
                    //判断共享数据是否到了末尾(还没有到末尾)
                    //随机一个删一个
                    Collections.shuffle(list);
                    int index = list.get(0);
                    System.out.println(getName() + "又产生了一个" + index + "元大奖");

                    list.remove(0);

                }
            }
            /*
            把sleep代码写在锁的外面
            因为当线程1进去了,如果你sleep写在锁里面,导致线程1睡了,线程2就无法进入锁了。
            写在外面,线程1执行完了,锁就开了,线程1睡100ms 线程2就有机会抢到cpu执行权
             */
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}
package lx5;

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

public class Test {
    public static void main(String[] args) {
        /*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
                             每次抽出一个奖项就打印一个(随机)
            	抽奖箱1 又产生了一个 10 元大奖
            	抽奖箱1 又产生了一个 100 元大奖
            	抽奖箱1 又产生了一个 200 元大奖
            	抽奖箱1 又产生了一个 800 元大奖
            	抽奖箱2 又产生了一个 700 元大奖
            	.....
        */

        //创建抽奖箱奖池
        ArrayList<Integer> list=new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,2,80,300,700);
        MyThread t1=new MyThread(list);
        MyThread t2=new MyThread(list);
        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");
        t1.start();
        t2.start();



    }
}

 

练习6

方法1 

package lx6;
 /*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
            每次抽的过程中,不打印,抽完时一次性打印(随机)    在此次抽奖过程中,抽奖箱1总共产生了6个奖项。
                分别为:10,20,100,500,2,300最高奖项为300元,总计额为932元
            在此次抽奖过程中,抽奖箱2总共产生了6个奖项。
                分别为:5,50,200,800,80,700最高奖项为800元,总计额为1835元
        */

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

public class MyThread extends Thread {
    //共享数据
    // 奖励的金额
    ArrayList<Integer> list;

    public MyThread(ArrayList<Integer> list) {
        this.list = list;
    }

    //线程1的
    static ArrayList<Integer> list1 = new ArrayList<>();
    //线程2的
    static ArrayList<Integer> list2 = new ArrayList<>();
/*
我们采用随机抽一个删一个的方法
 */

    @Override
    public void run() {
        //1.循环
        while (true) {

            //同步代码块
            synchronized (MyThread.class) {
                //判断共享数据是否到了末尾(到了末尾)

                if (list.size() == 0) {

                    break;
                } else {
                    //判断共享数据是否到了末尾(还没有到末尾)
                    //随机一个删一个
                    Collections.shuffle(list);
                    int index = list.get(0);
                    //  System.out.println(getName() + "又产生了一个" + index + "元大奖");

                    list.remove(0);
                    if ("抽奖箱1".equals(getName())) {
                        list1.add(index);
                    } else {
                        list2.add(index);
                    }

                }

            }
            /*
            把sleep代码写在锁的外面
            因为当线程1进去了,如果你sleep写在锁里面,导致线程1睡了,线程2就无法进入锁了。
            写在外面,线程1执行完了,锁就开了,线程1睡100ms 线程2就有机会抢到cpu执行权
             */
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        int sum1 = 0;
        int max1 = 0;
        for (Integer i : list1) {
            sum1 += i;
            if (max1 < i) {

                max1 = i;
            }

        }
        int sum2 = 0;
        int max2 = 0;
        for (Integer i : list2) {
            sum2 += i;
            if (max2 < i) {

                max2 = i;
            }

        }
        if ("抽奖箱1".equals(getName())) {
            System.out.println(getName() + list1 + "最高奖项为" + max1 + "元,总计额为" + sum1 + "元");
        } else {
            System.out.println(getName() + list2 + "最高奖项为" + max2 + "元,总计额为" + sum2 + "元");
        }

    }


}
package lx6;

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

public class Test {
    public static void main(String[] args) {
       /*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
            每次抽的过程中,不打印,抽完时一次性打印(随机)    在此次抽奖过程中,抽奖箱1总共产生了6个奖项。
                分别为:10,20,100,500,2,300最高奖项为300元,总计额为932元
            在此次抽奖过程中,抽奖箱2总共产生了6个奖项。
                分别为:5,50,200,800,80,700最高奖项为800元,总计额为1835元
        */

        //创建抽奖箱奖池
        ArrayList<Integer> list=new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,2,80,300,700);
        MyThread t1=new MyThread(list);
        MyThread t2=new MyThread(list);
        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");
        t1.start();
        t2.start();



    }
}

 

每个线程都有自己独立的栈空间 

run方法里的集合是独立的,互相独立的

方法2

把集合的创建放在run方法里面,每个线程都会执行run方法,创建出不同空间的集合

package lx7;
 /*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
            每次抽的过程中,不打印,抽完时一次性打印(随机)    在此次抽奖过程中,抽奖箱1总共产生了6个奖项。
                分别为:10,20,100,500,2,300最高奖项为300元,总计额为932元
            在此次抽奖过程中,抽奖箱2总共产生了6个奖项。
                分别为:5,50,200,800,80,700最高奖项为800元,总计额为1835元
        */

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

public class MyThread extends Thread {
    //共享数据
    // 奖励的金额
    ArrayList<Integer> list;

    public MyThread(ArrayList<Integer> list) {
        this.list = list;
    }


/*
我们采用随机抽一个删一个的方法
 */

    @Override
    public void run() {
        //创建集合 存放抽奖的奖项 这些集合都是根据线程的创建而创建的 就是每个线程创建一个集合
        ArrayList<Integer> boxList = new ArrayList<>();
        //1.循环
        while (true) {

            //同步代码块
            synchronized (MyThread.class) {
                //判断共享数据是否到了末尾(到了末尾)

                if (list.size() == 0) {
                    break;
                } else {
                    //判断共享数据是否到了末尾(还没有到末尾)
                    //随机一个删一个
                    Collections.shuffle(list);
                    int index = list.get(0);
                    list.remove(0);
                    //每个线程对对应的集合添加元素(集合不同)
                    boxList.add(index);

                }

            }
            /*
            把sleep代码写在锁的外面
            因为当线程1进去了,如果你sleep写在锁里面,导致线程1睡了,线程2就无法进入锁了。
            写在外面,线程1执行完了,锁就开了,线程1睡100ms 线程2就有机会抢到cpu执行权
             */
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        int sum = 0;
        int max = 0;
        for (Integer i : boxList) {
            sum += i;
            if (max < i) {

                max = i;
            }

        }
        //这里看起来只是打印一个集合,本质上是根据线程的多少打印出不同的集合
        System.out.println(getName() + boxList + "最高奖项为" + max + "元,总计额为" + sum + "元");


    }


}

package lx7;
import java.util.ArrayList;
import java.util.Collections;

public class Test {
    public static void main(String[] args) {
        /*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
            每次抽的过程中,不打印,抽完时一次性打印(随机)    在此次抽奖过程中,抽奖箱1总共产生了6个奖项。
                分别为:10,20,100,500,2,300最高奖项为300元,总计额为932元
            在此次抽奖过程中,抽奖箱2总共产生了6个奖项。
                分别为:5,50,200,800,80,700最高奖项为800元,总计额为1835元
        */

        //创建抽奖箱奖池
        ArrayList<Integer> list=new ArrayList<>();
        Collections.addAll(list,10,5,20,50,100,200,500,800,2,80,300,700);
        MyThread t1=new MyThread(list);
        MyThread t2=new MyThread(list);
        MyThread t3=new MyThread(list);
        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");
        t3.setName("抽奖箱3");

        t1.start();
        t2.start();
        t3.start();
    }
}

这个方法强调的是每个线程创建出不同的集合,每个线程都有自己的集合

练习7

package lx8;


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

public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
           /*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为    "抽奖箱1", "抽奖箱2"
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
            在此次抽奖过程中,抽奖箱1总共产生了6个奖项,分别为:10,20,100,500,2,300
        	    最高奖项为300元,总计额为932元
            在此次抽奖过程中,抽奖箱2总共产生了6个奖项,分别为:5,50,200,800,80,700
            	最高奖项为800元,总计额为1835元

            在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为800元
            核心逻辑:获取线程抽奖的最大值(看成是线程运行的结果)

            以上打印效果只是数据模拟,实际代码运行的效果会有差异
        */
//创建抽奖箱奖池
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 10, 5, 20, 50, 100, 200, 500, 800, 2, 80, 300, 700);

        /*
         1.定义一个类MyCallable实现Callable接口
        2.在MyCallable类中重写call()方法  有返回值的表示多线程运行的结果
        3.创建MyCallable类的对象 表示多线程要执行的任务
        4.创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数  作用:管理多线程运行的结果
        5.创建Thread类的对象,把FutureTask对象作为构造方法的参数 表示线程
        6.启动线程
        7.再调用get方法,就可以获取线程结束之后的结果。
         */
        Mycallable m = new Mycallable(list);
        FutureTask<Integer> ft = new FutureTask<>(m);
        Thread t1 = new Thread(ft);
        Thread t2 = new Thread(ft);
        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");
        t1.start();
        t2.start();
        //获取多线程的运行结果
        Integer result = ft.get();
        System.out.println(result);

    }
}

package lx8;


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

public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
           /*
            有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700};
            创建两个抽奖箱(线程)设置线程名称分别为    "抽奖箱1", "抽奖箱2"
            随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
            在此次抽奖过程中,抽奖箱1总共产生了6个奖项,分别为:10,20,100,500,2,300
        	    最高奖项为300元,总计额为932元
            在此次抽奖过程中,抽奖箱2总共产生了6个奖项,分别为:5,50,200,800,80,700
            	最高奖项为800元,总计额为1835元

            在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为800元
            核心逻辑:获取线程抽奖的最大值(看成是线程运行的结果)

            以上打印效果只是数据模拟,实际代码运行的效果会有差异
        */
//创建抽奖箱奖池
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 10, 5, 20, 50, 100, 200, 500, 800, 2, 80, 300, 700);

        /*
         1.定义一个类MyCallable实现Callable接口
        2.在MyCallable类中重写call()方法  有返回值的表示多线程运行的结果
        3.创建MyCallable类的对象 表示多线程要执行的任务
        4.创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数  作用:管理多线程运行的结果
        5.创建Thread类的对象,把FutureTask对象作为构造方法的参数 表示线程
        6.启动线程
        7.再调用get方法,就可以获取线程结束之后的结果。
         */

        //创建多线程要运行的参数对象
        Mycallable m = new Mycallable(list);
        //创建多线程运行结果的管理者对象
        FutureTask<Integer> ft1 = new FutureTask<>(m);
        FutureTask<Integer> ft2 = new FutureTask<>(m);
        //创建线程对象
        Thread t1 = new Thread(ft1);
        Thread t2 = new Thread(ft2);
        t1.setName("抽奖箱1");
        t2.setName("抽奖箱2");
        t1.start();
        t2.start();
        //获取多线程的运行结果
        Integer result1 = ft1.get();
        System.out.println(result1);
        Integer result2 = ft2.get();
        System.out.println(result2);
        //  在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为800元
        if (result1 > result2) {

            System.out.println("在此次抽奖过程中,抽奖箱1中产生了最大奖项,该奖项金额为800元");
        } else {

            System.out.println("在此次抽奖过程中,抽奖箱2中产生了最大奖项,该奖项金额为800元");
        }

    }
}

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部