黑马程序员技术交流社区
标题:
java多线程问题
[打印本页]
作者:
289314335
时间:
2016-9-30 23:30
标题:
java多线程问题
假设抽奖箱中有100个号码(依次从1到100),开启两个线程, 共随机抽选出10个号码,并在控制台上打印出两个线程分别抽选了哪些号码? 提示:(两个线程不能抽取同一个号码,已经抽取的号码不能再次抽取; 不限定两个线程抽取的个数一样,总共抽选10个即可,线程名自定义)。
问题是,我按照多线程的正规写法用了同步代码块,锁对象也是类的字节码文件,但是输出的时候每次只有一个线程进行输出,用了sleep()方法也切换不了线程,
类采用的是继承Thread,怀疑是不是创建了两个Thread,出现了两个对象的问题,但是用了实现runnable接口结果还是一样的。
求助哪里出了问题?下面是代码:
public class ChouJiang {
public static void main(String[] args) {
Thread t1 = new Chou();
t1.setName("线程一");
Thread t2 = new Chou();
t2.setName("线程二");
t1.start();
t2.start();
}
}
class Chou extends Thread {
// 100个号码(依次从1到100)
static ArrayList<Integer> list = new ArrayList<Integer>();
static HashSet<Integer> hs = new HashSet<Integer>();
static {
for (int i = 1; i <= 100; i++) {
list.add(i);
}
while (hs.size() < 10) {
Random r = new Random();
int j = r.nextInt(100) + 1; // 随机数获取1-100
hs.add(j);
}
}
@Override
public void run() {
// 共随机抽选出10个号码, 并在控制台上打印出两个线程分别抽选了哪些号码
// * 提示:(两个线程不能抽取同一个号码,已经抽取的号码不能再次抽取;
synchronized (ChouJiang.class) {
while (list.size() > 90) {
for (Integer num : hs) {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()
+ "抽取了:" + num + "号球");
list.remove(num);
} catch (Exception e) {
}
}
}
}
}
}
作者:
Reisen
时间:
2016-9-30 23:30
1.直接new两个Thread子类,就相当于两个抽奖箱了,应该实现Runnable接口作为参数传入Thread
2.sleep方法是不会释放锁的,wait()方法才会,一个线程上锁后会一直执行到while循环读完后才释放锁,此时list.size() == 90不满足条件另一个线程进入直接跳过中间的所有代码...
作者:
guhaoa
时间:
2016-10-2 13:41
你还需要解答吗,我可以帮你解决
作者:
读书可以当饭吃
时间:
2016-10-2 14:01
本帖最后由 读书可以当饭吃 于 2016-10-2 14:11 编辑
这是我写的,注释写得不是很清楚,看不懂再问吧
import java.util.ArrayList;
import java.util.Random;
public class Test2 {
/**
* 100个数的抽奖箱中由两个线程共随机抽取10个数
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
final ArrayList<Integer> list = new ArrayList<>(); //创建抽奖箱
final ArrayList<Integer> list2 = new ArrayList<>(); //创建存放甲抽得的数的箱子
final ArrayList<Integer> list3 = new ArrayList<>(); //创建存放乙抽得的数的箱子
for(int i = 1;i<=100;i++){ //向抽奖箱添加被抽取的数
list.add(i);
}
final Random ra = new Random(); //创建生成随机数对象
Runnable r = new Runnable() { //创建Runnable接口子类对象
int y = 100; //用于记录抽奖箱剩余的数有多少个
int z = 0; //用于记录抽取了多少个数
public void run() {
while(true){
synchronized (list) { //加锁保证线程同步,不会重复抽取
if(z<10){
//随机产生一个1-y范围内的整数x
int x = ra.nextInt(y)+1;
//从list集合中删除索引为x的元素并用in记录
Integer in = list.remove(x);
//如果线程名为"甲",则将删除的元素添加到list2集合
if("甲".equals(Thread.currentThread().getName())){
list2.add(in);
}else if("乙".equals(Thread.currentThread().getName())){
list3.add(in);
}
//集合长度变短,对应的求索引的范围应该变小
y--;
//记录抽取了多少个元素
z++;
}else{
return; //抽出10则结束线程
}
}
}
}
};
Thread t1 = new Thread(r); //传入Runnable接口子类对象创建线程
Thread t2 = new Thread(r);
t1.setName("甲"); //设置线程名字
t2.setName("乙");
t1.start(); //开启线程
t2.start();
t1.join(); //主线程等待t1线程完成后执行
t2.join();
System.out.println(t1.getName()+"抽取了:"+list2);
System.out.println(t2.getName()+"抽取了:"+list3);
}
}
作者:
fdzx0707fh
时间:
2016-10-4 20:03
**********synchronized (ChouJiang.class)******
这个锁用错了 ,你换成this就可以了
作者:
fdzx0707fh
时间:
2016-10-4 20:06
fdzx0707fh 发表于 2016-10-4 20:03
**********synchronized (ChouJiang.class)******
这个锁用错了 ,你换成this就可以了
synchronized(ThreadTest.class)是对ThreadTest这个类进行加锁,类里面的属性,方法都是同步的,是针对于特定的类的~~
synchronized(this){}是对{}这里面的内容进行加锁的,仅仅是针对于当前对象的
作者:
wangkai426
时间:
2016-10-6 22:20
线程安全问题比较头疼
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2