一个java多线编程的问题
答案:6 悬赏:10 手机版
解决时间 2021-01-07 09:59
- 提问者网友:最美的风景
- 2021-01-07 03:07
一个java多线编程的问题
最佳答案
- 五星知识达人网友:白昼之月
- 2021-01-07 03:57
这个问题很明显啊~。在当前线程中执行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]);
} 还不喜欢的话,那就只能将阻塞信号放到内部类里,然后反射出来了。不反射的话就声明一个类。
所以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
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.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]);
} 还不喜欢的话,那就只能将阻塞信号放到内部类里,然后反射出来了。不反射的话就声明一个类。
全部回答
- 1楼网友:长青诗
- 2021-01-07 08:15
是使用Object中有关线程的方法,但试了都有异常
- 2楼网友:野味小生
- 2021-01-07 08:09
这个问题好抽象,不知道有什么意思, 看起来是没法实现啦
- 3楼网友:低血压的长颈鹿
- 2021-01-07 06:56
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么?
- 4楼网友:一叶十三刺
- 2021-01-07 05:56
public static void magic(final Object obj) {
new Thread() {
@Override
public void run() {
try {
obj.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}追问没用且抛出异常。wait不是你这么理解的,我也因此找不到一个巧妙的锁定obj的方法。
不过楼下的试了有效果
new Thread() {
@Override
public void run() {
try {
obj.wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}追问没用且抛出异常。wait不是你这么理解的,我也因此找不到一个巧妙的锁定obj的方法。
不过楼下的试了有效果
- 5楼网友:我住北渡口
- 2021-01-07 05:18
这个东西不错,持续关注
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();
}
}
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();
}
}
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯