子线程中开启一个主线程去获取某些数据,此时子线程要处理等待状态,获取成功以后继续执行子线程中以后的代码.java
final Object obj = new Object();
new Thread(){
@Override
public void run() {
super.run();
//经过Handler建立一个主线程.
new Handler(getMainLooper()).post(new Runnable() {
@Override
public void run() {
synchronized (obj) {
//模拟主线程耗时操做
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
str = "WangChao";
Log.e("CHAO", "run 2" + str);
obj.notify();
}
}
});
Log.e("CHAO","run 1");
synchronized (obj) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//子线程须要主线程的返回参数
if (str != null) {
Log.e("CHAO", "run 3" + str);
}
}
}
}.start();复制代码
运行可知先运行的是run 1 ,以后是主线程中的run 2 ,而后是子线程中的 run 3.这样就能够达到咱们想要的结果.运行结果以下:com.example.wang.threaddemo E/CHAO: run 1
com.example.wang.threaddemo E/CHAO: run 2WangChao
com.example.wang.threaddemo E/CHAO: run 3WangChao复制代码
synchronized关键字的用法
被synchronized修饰的方法称为同步方法,默认的锁是当前对象.所谓同步方法是若是有一个线程正在访问该方法的时候,其余的方法调用到该方法的时候将进入等待的状态.当有多个同步方法的时候,一旦一个线程调用了其中的一个同步方法,便对当前对象加锁,其余的线程调用拥有同对象锁的其它同步方法时会处于等待的状态,等以前的线程释放掉对象锁以后继续执行.
1.去修饰方法 : 对象锁默认是当前对象 this .bash
public synchronized void method2(){
Log.e("CHAO", "method2: " + Thread.currentThread().getName());
}复制代码
还能够这样写:多线程
public void method2(){
synchronized (this) {
Log.e("CHAO", "method2: " + Thread.currentThread().getName());
}
}复制代码
2.同步语句块 : 能够本身去设置加锁的对象.ide
synchronized (obj) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
str = "WangChao";
Log.e("CHAO", "2" + str);
obj.notify();
}复制代码
这里须要注意的是synchronized (obj) 里面的参数,也就是要给那个对象加锁.这个对象必须是惟一的切多个线程都能拿到这个对象.(再使用Stirng最为对象锁的时候必定要注意String的从新赋值,一旦赋值改对象就改变了再也不是咱们以前加锁的对象),一般能够本身去建立一个final 的 Object类去加锁,也可使用this,Class对象等.oop
3.同步静态方法啊: 加锁对象是当前的Class对象.post
public static synchronized void method1(){
int count = 0;
for (int i = 0; i < 120000; i++) {
count++;
}
Log.e("CHAO", "method1: " + Thread.currentThread().getName());
}复制代码
同不得静态方法再多线程中的调用和非静态的是一致的.ui
wait()
首先wait()是属于Object类的方法,从源码给出的解释来看,wait()方法能够作到以下几点:
(1)首先,调用了wait()以后会引发当前线程处于等待状状态。
(2)其次,每一个线程必须持有该对象的monitor(监视)。若是在当前线程中调 用wait()方法以后,该线程就会释放monitor的持有对象并让本身处于等 待状态。
(3)若是想唤醒一个正在等待的线程,那么须要开启一个线程经过notify()或者notifyAll()方法去通知正在等待的线程获取monitor对象。如此,该线程便可打破等待的状态继续执行代码.this
注意: wait()方法要使用在synchronized修饰的方法里面要否则会报异常,而且是synchronized()加锁的那个对象调用该方法.异常以下:spa
java.lang.IllegalMonitorStateException: object not locked by thread before wait()复制代码
notify() , nitifyAll()
notify()是属于Object类的方法.notify唤醒一个在这个对象上等待的线程监控。若是有任何线程在等待这个对象,其中一个线程被选择被唤醒。这个选择是任意的,而且发生在执行的自由裁量。一个线程在一个对象上等待经过调用wait()等方法来监视。nitifyAll唤醒全部的再等待中的线程.线程
注意:nitify唤醒的线程会在该线程的wiat以后继续执行,特别要注意的是调用wiat的同步语句块的对象锁要和nitify的同步语句块的对象锁是同一个,不然的话你是唤醒不了wait状态的.
final Object obj = new Object();
new Thread(){
@Override
public void run() {
super.run();
new Handler(getMainLooper()).post(new Runnable() {
@Override
public void run() {
//注意这个加锁对象
synchronized (obj) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
str = "WangChao";
Log.e("CHAO", "2" + str);
//注意唤醒方法的调用者
obj.notify();
}
}
});
Log.e("CHAO","run"+1);
//注意这个加锁对象
synchronized (obj) {
try {
//注意等待方法的调用者
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (str != null) {
Log.e("CHAO", "3" + str);
}
}
}
}.start();复制代码
(1)在线程的运行过程当中,调用该线程持有monitor对象的wait()方法时,该线程首先会进入等待状态,并将本身持有的monitor对象释放。
(2)若是一个线程正处于等待状态时,那么唤醒它的办法就是开启一个新的线程,经过notify()或者notifyAll()的方式去唤醒。固然,须要注意的一点就是,必须是同一个monitor对象。
(3)sleep()方法虽然会使线程中断,可是不会将本身的monitor对象释放,在中断结束后,依然可以保持代码继续执行。
欢迎你们的点评和补充,喜欢的话就给个赞👍支持下吧~