本帖最后由 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.
|