永发信息网

一个java多线编程的问题

答案:6  悬赏:10  手机版
解决时间 2021-01-07 09:59
一个java多线编程的问题
最佳答案
这个问题很明显啊~。在当前线程中执行enter时最后把obj锁住情况下执行输出Step3, 那么我在其他线程中抢先把obj也锁住,而且永远不出线程的锁块。那当前线程永远获取不到obj的操作权啊。
所以magic中要新建个线程,线程是另一个类,这也是它给你参数加final的原因,final“可不是可有可不有的”,是题目给你的小提示。把magic这样写就好啦
public static void magic(final Object obj) {
new Thread(){
public void run(){
synchronized(obj){
while(true){
try{
Thread.sleep(5000);
}catch(Exception e){

}
}

}
}

}.start();
}追问这个方法楼下有人回答了,你的少了个sleep,我就花点时间测试了下,我在你的run方法里加了个打印,然后就发现如果执行玩了step 3后,这个线程才启动并进入run方法,所以另一个人有sleep方法来保证执行step 3之前,确保线程已启动,但那不是我要的答案。追答好吧,我还有方法,等下哈 ,刚才吃饭去了


其实那哥们那样儿也行,思路对的嘛,要等1秒。当然我这个更好。思路更好,虽然用的类好像还有更好的,但这个思路应该就是你要的了:
在magic中步骤1:找个方法将外层线程阻塞;
                       2:新建线程将obj锁死在里面;
                       3:放开外层线程,以保证Step2输出。
OK,我不知道你有没有接触过BlockingQueue,阻塞队列。java.util.concurrent.BlockingQueue
public static void magic(final Object obj) {
final BlockingQueue queue=new ArrayBlockingQueue(1);
    new Thread(){
     public void run(){
     synchronized(obj){
     try {
queue.put(1);
queue.put(1);
queue.put(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
            }
        }
    }.start();
    try {
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}

     1,新建阻塞队列,你跳过new Thread去看下面queue.take(),当然这个不能放上面,因为在队列里没有东西的情况下,当前线程会被阻塞,直到有东西put到队列中。好的这个queue.take()放在下面就是在让当前线程阻塞住,等待其他线程拿走obj的操作权。

      2,新建拿走obj操作权的线程,运行起来拿走obj的操作权,put第一句,用以放开外层线程,即take()通过,put第二句填满queue,put第三句,阻塞线程,(在queue放满的情况下put会等待直到有位置可放入。)这样就保证了我永远拿着obj的操作权。
     PS: 最后两个put我还是建议用循环sleep. 好像这个阻塞时间太长会被gc收走线程,或是其他什么的。我有更好方法了,想要的话追问下吧~
追问还有只用基本的java方法,不用想blockqueue那样里面本身就封装了东西的方式?追答当然有啦~~, 呵呵,其实你想想, 阻塞是什么 ?  就是死循环, while(true);就能阻塞当前线程。

那么,上面的思路就完全可以映射为以下代码:
public static void magic(final Object obj){
final boolean pass= false;
new Thread(){public void run(){synchronized(obj){while(pass=true);}}}.start();
while(!pass);
}但是,别忘了,final句柄是不允许更换引用地址的。所以想要完成需要,把boolean放到其他对象里就好,那方法就多了,看下面吧,数组实际上是个Object。 注释里还有两种,一种是List,一种是AtomicBoolean,都能完成需求。
public static void magic(final Object obj) {
// final List passList=new ArrayList();
// passList.add(false);
// new Thread(){public void run(){synchronized(obj){do{passList.set(0, true);}while(passList.get(0));}}}.start();
// while(!passList.get(0));

// final AtomicBoolean pass=new AtomicBoolean(false);
// new Thread(){public void run(){synchronized(obj){while(pass.getAndSet(true)||true);}}}.start();
// while(!pass.get());

final boolean[] pass=new boolean[1];
new Thread(){public void run(){synchronized(obj){while(pass[0]=true);}}}.start();
while(!pass[0]);
}    还不喜欢的话,那就只能将阻塞信号放到内部类里,然后反射出来了。不反射的话就声明一个类。
全部回答
是使用Object中有关线程的方法,但试了都有异常
这个问题好抽象,不知道有什么意思, 看起来是没法实现啦

package test;
public class Test {
public static void enter(Object obj) {
    System.out.println("STEP 1");
    magic(obj);
    System.out.println("STEP 2");
    synchronized(obj) {
         System.out.println("STEP 3");
    }
}
public static void magic(final Object obj) {
//请完成代码,使得STEP 3不被打印,并说明原理和思路
Runnable tt= new TestThread(obj);
Thread th = new Thread(tt);
th.start();
try {
//睡眠1s是为了防止主线程快于th线程,先获取到obj锁打印出step 3
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}    
 static class TestThread implements Runnable{
    
public Object obj;

public TestThread(Object obj){
this.obj=obj;
}

@Override
public void run() {
// 获取obj对象锁,一直循环,不释放
synchronized(obj){
for(int i=1;true;i++){
}
}
}
 
 }
public static void main(String[] args) {
    Object obj = new Object();
    Test.enter(obj);
//执行的结果是打印STEP 1和STEP 2,并停住
}
}追问改成内部类实现了,有作用。但sleep感觉是取巧,貌似不符合我的书上问题的要求。可以不要sleep么?
 public static void magic(final Object obj) {
        new Thread() {
            @Override
            public void run() {
                try {
                    obj.wait();
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }追问没用且抛出异常。wait不是你这么理解的,我也因此找不到一个巧妙的锁定obj的方法。
不过楼下的试了有效果
这个东西不错,持续关注
public static void magic(final Object obj) {
new Thread() {
@Override
public void run() {
synchronized(obj){
while(true){
}
}
}
}.start();
try {
Thread.holdsLock(obj);//改进,等下看看这个东西是怎么实现的!(额。不能算改进,只有在第一次运行将obj hold住之后才可以实现LZ想要的,回到原点了)
if(!Thread.holdsLock(obj)){
Thread.sleep(1000);//睡眠1s是为了防止主线程快于th线程,先获取到obj锁打印出step 3
}
}catch (Exception e) {
e.printStackTrace();
}
}
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
自己做自己吃的东西的心情说说
如何养野外草丛中抓的蜗牛
用L'Hospital法则求极限,感觉参考答案有
哪有小米山水楼图片。?
为什么你的瑜伽老师每节课都带你做扭转体式?
小炒带皮肘子的做法,小炒带皮肘子怎么做好吃
有没有在木风上下载系统的?
享利英文怎么读
9x4+1·5x=132怎么解
男子暗恋女同学六年,女孩登台涂磊直呼:他是
《情非得已》中的切音怎么练习?
新人求助武器战怎么打
谁都有落魄的时候,我风光的时候你们站在我左
爱一个人啊 需要多勇敢 。 是什么歌曲?
女生美甲脚趾什么颜色好看
推荐资讯
如图,圆与长方形的周长相等,面积相差12平方
糖浆的做法大全 简单制作糖浆怎么做
西安市莲湖区少年宫在莲湖公园坐10路在哪一站
kevindurant什么意思
老人高压170有危险吗
冬天甘肃蔬菜贵吗?
岳塘区湘潭正宗扬州万泉足艺这个地址怎么能查
个人参加投资理财讲座的意义在哪
请问625x625怎么算简单
蓝悦电脑音响没有声音怎么办
主宰穿越小说txt全集免费下载
Ps4关于漫威或DC的游戏
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?