使用notify()报错跳出问题

使用notify()报错跳出问题

老师您好,程序去掉notify其他部分都正常运行,只要触发notify就跳出,麻烦您帮我看一下,下面是我的线程类和主activity. 另外有很多注释的代码您直接忽略就好。

package com.example.zuoye_3_1;

import android.os.Handler;
import android.os.Message;

import androidx.annotation.NonNull;

//线程类

public class gamethread implements Runnable {
   //声明地鼠xy轴变量和一个handler
   private int xcoordinate;
   private int ycoordinate;

   private Handler handler1;
//    private Handler handler2=new Handler(){  public void handleMessage(@NonNull Message msg) {
//        super.handleMessage(msg);
//       gamethread.this.notifyAll();
////            Toast.makeText(MainActivity.this, "1"+msg.arg1+msg.arg2,Toast.LENGTH_SHORT).show();
//
//    }};
   //构造方法传handler.
   public gamethread(Handler handler){
       this.handler1=handler;
   }
   //线程,随机数字传给主线程改地鼠位置。
   @Override
   public void run() {
       for(int i =0;i<10;i++) {
           this.xcoordinate = (int) (Math.random() * 300);
           this.ycoordinate = (int) (Math.random() * 600);
           Message coordinate = new Message();
//            coordinate.obj=this.handler2;
           coordinate.arg1 = this.xcoordinate;
           coordinate.arg2 = this.ycoordinate;
           coordinate.what = 1;
           handler1.sendMessage(coordinate);
//            try {
//
//                Thread.sleep((int) ((Math.random() * 500)+500));
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }

           //调用wait延迟地鼠换位时间。
           synchronized (this){
               try {
                   this.wait(3000);
//               a.wait((long) ((Math.random() * 500)+500));
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
       }

   }
}



package com.example.zuoye_3_1;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
//主activity.
public class MainActivity extends AppCompatActivity {
   //声明图片按钮等组件,k为记录打地鼠的数量
   public ImageView target;
   public Button gamebutton;
   public TextView gametextView;
   public int k=0;
   //用来负责传递数据修改地鼠位置的handler
   private Handler handler1=new Handler(){
       @Override
       public void handleMessage(@NonNull Message msg) {
           super.handleMessage(msg);
           target.setX(msg.arg1);
           target.setY(msg.arg2);
//            handler2=(Handler)msg.obj;
//            Toast.makeText(MainActivity.this, "1"+msg.arg1+msg.arg2,Toast.LENGTH_SHORT).show();

       }
   };
//    private Handler handler2;
   Thread a;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       //实例化
       target=(ImageView)findViewById(R.id.target);
      gamebutton =(Button)findViewById(R.id.gamebutton);
       gametextView=findViewById(R.id.gametextView);


   }

   //用来调用gamethread线程,修改组件文字的方法
   public void gameT() {
       gamebutton.setEnabled(false);
       gamebutton.setText("游戏中");
       gametextView.setText("开始啦");

      a= new Thread(new gamethread(handler1));
      a.start();
//       synchronized (a){
//           try {
//               a.wait();
////               a.wait((long) ((Math.random() * 500)+500));
//           } catch (InterruptedException e) {
//               e.printStackTrace();
//           }
//       }
           }
   //用来对按钮做判断的方法。
   public void gamestart(View v){
       switch (v.getId()){
           case R.id.gamebutton:
               gameT();
               break;
           case R.id. target:
//               handler2.sendEmptyMessage(1);
              k++;
               gametextView.setText("打到"+k+"只,共十只");
//
       //本意为在点击地鼠时,解开gamethread循环中的wait()延迟,使地鼠换位置,但是点击直接报错,Caused by: java.lang.IllegalMonitorStateException: object not locked by thread before notify()
             a.notify();
               break;

       }


       }
}

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

1)同学理解错了:为什么要notify(),就是被锁定了synchronized。要保证你调用的notify 的对象,是你synchronized 的对象。才不会object not locked by thread before notify()。  2)对于作业不需要锁定,地鼠要一个一个的出,出完一个,再出第二个,并不是10只地鼠同时出的,所以你不用锁,也不用notify()。祝:学习愉快

  • 慕田峪2007516 提问者 #1
    老师我代码里锁的是当前线程,我code里只有一个a线程,地鼠绑定的按钮也是a.notify(),为什么不是一个对象呢? 第二点老师我是这个意思,地鼠出现一只,下一只出现时间由wait(时间)控制,但是一旦打到地鼠(点击地鼠图标),地鼠应该直接消失,也就是解除wait()的状态,去下一次for循环里改变位置,要不然地鼠被打到,图片还在原地等下一次换位置的时间。所以我一直想在打到袋鼠时候用notify()跳过一次等待。
    2020-05-20 16:08:53
  • 好帮手慕雪 回复 提问者 慕田峪2007516 #2
    1)每次gameT()里a= new Thread(new gamethread(handler1));只有这一个新对象,不可能会锁对吧,当然也就唤醒不了。a.wait();也不会被多个线程同时执行的。2)你把它想复杂了,不用锁机制,你就只监听那个地鼠点击事件就行了。点击到了,就把它移位,相当于第二只地鼠出现了。
    2020-05-20 17:20:35
  • 慕田峪2007516 提问者 回复 好帮手慕雪 #3
    明白了,谢谢您耐心解答。
    2020-05-20 17:23:17
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
2.Android 网络操作与流行框架
  • 参与学习           人
  • 提交作业       220    份
  • 解答问题       1800    个

本阶段是联网及数据处理的必备技能。课程从网络基础知识到线程间协同工作、异步下载处理;从文件存储、到轻量级数据库SQLite的使用;最后利用最流程的第三方框架助你快速开发企业级APP。

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师