A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 xiekai_sjz 于 2017-11-18 17:22 编辑

    我们在学习线程的时候常常会遇到抽奖池的类似问题,下面就结合一个抽奖池的例题来讲接下线程需要注意的问题.
[Java] 纯文本查看 复制代码
/*
          有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为 {10,5,20,50,100,200,500,800,2,80,300,700}; 
        创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”,随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
        
        每次抽的过程中,不打印,抽完时一次性打印(随机)
                在此次抽奖过程中,抽奖箱1总共产生了5个奖项,分别为:10,20,100,500,2
                在此次抽奖过程中,抽奖箱2总共产生了6个奖项,分别为:5,50,200,800,80

 */

public class Test {
        public static void main(String[] args) {
                MyRunnable run = new MyRunnable();
                Thread t1 = new Thread(run);
                Thread t2 = new Thread(run);
                t1.setName("抽奖池一");
                t2.setName("抽奖池二");
                t1.start();
                t2.start();
        }
}

[Java] 纯文本查看 复制代码
import java.util.ArrayList;
import java.util.Random;

public class MyRunnable implements Runnable{
        //模拟总的抽奖池,存储所有未被抽取的奖项
        static ArrayList<Integer> list = new ArrayList<>();
        
        //静态代码块,用来初始化抽奖池中的数据
        static{
                int[] arr = {10, 5, 20, 50, 100, 200, 500, 800, 2, 80, 300};
                for(int i=0;i<arr.length;i++){
                        list.add(arr[i]);
                }
        }

        @Override
        public void run() {
                String name = Thread.currentThread().getName();
                //每个抽奖箱都有一个集合用来存储该抽奖箱中抽取的奖项
                ArrayList<Integer> newList = new ArrayList<>();
                while(true){
                        synchronized (this) {
                                try {
                                        Thread.sleep(300);
                                } catch (InterruptedException e) {
                                        e.printStackTrace();
                                }
                                //当总的抽奖池为空时,抽奖完毕,打印每个抽奖箱的抽奖结果
                                if(list.size() <=0){
                                        System.out.println(name+"产生了"+newList.size()+"个奖,分别是"+newList);
                                        break;
                                }
                                Random r = new Random();
                                //生成随机索引
                                int index= r.nextInt(list.size());
                                //把index位置的奖项从总的抽奖池中删除,并添加到抽奖箱中
                                newList.add(list.remove(index));
                        }
                }
        }
}


java线程需要注意的几个问题如下:
一. 创建线程的两种方式
    方式一:继承Thread类创建线程类
[Java] 纯文本查看 复制代码
public class ThreadTest {
        public static void main(String[] args) {
                MyThread t1 = new MyThread();
                MyThread t2 = new MyThread();
                t1.start();
                t2.start();
        }
}

class MyThread extends Thread{
        @Override
        public void run() {
                super.run();
        }
}
    方式二:通过Runnable接口创建线程类
[Java] 纯文本查看 复制代码
public class RunnableTest {
        public static void main(String[] args) {
                MyRunnable runnable = new MyRunnable();
                Thread t1 = new Thread(runnable);
                Thread t2 = new Thread(runnable);
                t1.start();
                t2.start();
        }

}

class MyRunnable implements Runnable{
        @Override
        public void run() {
                
        }
}

二.start()方法和run()方法的区别
    run()方法:在本线程内调用该Runnable对象的run()方法,可以重复多次调用;
    start()方法:启动一个线程,调用该Runnable对象的run()方法,不能多次启动一个线程;

三.同步代码块的锁对象
    继承Thread类的同步代码块的锁对象可以是该类的字节码文件对象,但是不可以是this.
    实现Runnable接口的同步代码块的锁对象既可以是该类的字节码文件对象,也可以是this.   


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马