线程间通信原理
从操作系统的角度讲,线程间通信比进程间通信要容易的多,因为线程之间可以共享进程的内存空间。因此,他们可以共享位于进程全局数据区和栈和堆上的所有内容。
唯一只属于某个线程的就是线程的栈-------它可以存放只属于线程的对象。
下面逐一解读线程间通信方式:
1. 共享进程的变量
这是最基本的通信方式,但要注意不要共享线程栈上的变量,因为它随时可能被某个线程销毁,而另一个线程就无法访问它了。
所以Java编译器不允许使用栈上的变量来共享。
例子1:
如下面这个编译器是会报错的,
protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); int i=0; Thread a=newThread(new Runnable(){ @Override public voidrun() { // TODOAuto-generated method stub i++; } }); }
上面的自动变量i可以看做是进程的变量,但它有可能被申请它的线程销毁,因为无法用来进行共享。
例子2:
正面的例子比如android中的handler,它是需要在进程空间共享的。
2. TLS(Thread Local Storage)
线程本地存储,本质上是存储一系列线程号和Looper对象的key-value键值对。
比如Android的Looper
public finalclass Looper { privatestatic final String TAG = "Looper"; // sThreadLocal.get() will return null unlessyou've called prepare(). static final ThreadLocal<Looper>sThreadLocal = new ThreadLocal<Looper>(); private static Looper sMainLooper; //guarded by Looper.class final MessageQueue mQueue; final Thread mThread; private Printer mLogging; }
Looper有一个静态的
static final ThreadLocal<Looper> sThreadLocal = newThreadLocal<Looper>();
ThreadLocal本质上是一系列线程号和Looper对象的key-value键值对,因为sThreadLocal是静态的,所以它为所有的线程所共享。
而sThreadLocal.get()就是获取当前线程对应的Looper。
例子:
起一个Worker线程来做事情
private static class Worker implementsRunnable { …… publicvoid run() { synchronized(mLock) { Looper.prepare(); mLooper= Looper.myLooper(); mLock.notifyAll(); } Looper.loop(); } publicvoid quit() { mLooper.quit(); } }
其中Looper.prepare()就是重新创建一个Looper,查看Looper源码的话,就调用了
sThreadLocal.set(new Looper(quitAllowed));
也就是往sThreadLocal插入了一个键值对。
另外一个Looper有一个MessageQueue,用来存储Message。
在Looper和Handler两者中,Looper实现了线程间通信,Handler是对Looper的封装,是Looper的友好接口,方便用户调用而已。而且Handler在各个线程间共享,以达到多线程通信的目的。
3. 并发,同步和互斥(Java)
3.1 Synchronize关键字
这个是monitor,保证互斥的,一块代码不能同时被两个线程访问。
3.2 Semaphore类
Java中的Semaphore类,是进行并发控制的,也就是说,它可以限制访问一个资源(或代码块)的线程数目。当设定的线程数目是1时,并发其实就退化到了互斥。
3.3 Lock类
Lock类也可以取代Object的Notify和Wait
3.4 对象锁
Synchronized+Object的Notify和wait,这三个一起构成了同步。
比如下面这段程序,保证了Thread A和Thread B是交替执行的。
例子:
public void onClick_start_thread_a(View v) { logger.d("onClick_start_thread_a"); Runnable r = new Runnable() { @Override public void run() { // TODO Auto-generated method stub while (true) { synchronized (flag) { System.out.println("Thread A!"); flag.notifyAll(); try { flag.wait(); } catch(InterruptedException e) { e.printStackTrace(); } } } } }; Thread t = new Thread(r); t.start(); } public voidonClick_start_thread_b(View v) { logger.d("onClick_start_thread_b"); Runnable r = new Runnable() { @Override public void run() { // TODO Auto-generated method stub while (true) { synchronized (flag) { System.out.println("Thread B!"); flag.notifyAll(); try { flag.wait(); } catch (InterruptedExceptione) { e.printStackTrace(); } } } } }; Thread t = new Thread(r); t.start(); }
附:
下面附上一段使用Handler,Looper的代码
private static class Worker implementsRunnable { privatefinal Object mLock = new Object(); privateLooper mLooper; /** * Createsa worker thread with the given name. The thread * thenruns a {@link android.os.Looper}. * @paramname A name for the new thread */ Worker(Stringname) { Threadt = new Thread(null, this, name); t.setPriority(Thread.MIN_PRIORITY); t.start(); synchronized(mLock) { while(mLooper == null) { try { mLock.wait(); } catch (InterruptedException ex) { } } } } publicLooper getLooper() { returnmLooper; } publicvoid run() { synchronized(mLock) { Looper.prepare(); mLooper= Looper.myLooper(); mLock.notifyAll(); } Looper.loop(); } publicvoid quit() { mLooper.quit(); } } package com.example.test; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; public classProgressTestActivity extends Activity { privateProgressBar progress; private TextView text; private Worker mWorker; privateWorkerHandler mWorkerHandler; private UIHandlermUIHandler; @Override public void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); progress =(ProgressBar) findViewById(R.id.progressBar1); text =(TextView) findViewById(R.id.textView1); mWorker = new Worker("artworker"); mWorkerHandler = newWorkerHandler(mWorker.getLooper()); mUIHandler = newUIHandler(Looper.myLooper()); } public voidstartProgress(View view) { Message msgObj = mWorkerHandler.obtainMessage(); msgObj.what = 2; mWorkerHandler.sendMessage(msgObj); } // Simulatingsomething timeconsuming private voiddoFakeWork() { try { Thread.sleep(1000); } catch(InterruptedException e) { e.printStackTrace(); } } private static class Worker implements Runnable{ private final Object mLock = new Object(); private Looper mLooper; /** * Creates a worker thread with the given name.The thread then runs a * {@link android.os.Looper}. * * @param name * A name for the new thread */ Worker(String name) { Thread t = new Thread(null, this, name); t.setPriority(Thread.MIN_PRIORITY); t.start(); synchronized (mLock) { while (mLooper == null) { try { mLock.wait(); } catch(InterruptedException ex) { } } } } public LoopergetLooper() { return mLooper; } public void run() { synchronized (mLock) { Looper.prepare(); mLooper = Looper.myLooper(); mLock.notifyAll(); } Looper.loop(); } public void quit(){ mLooper.quit(); } } public class UIHandlerextends Handler { private long mAlbumId = -1; public UIHandler(Looperlooper) { super(looper); } @Override public voidhandleMessage(Message msg) { if (msg.what == 1) { int value =msg.getData().getInt("value"); progress.setProgress(value); MessagemsgObj = mWorkerHandler.obtainMessage(); msgObj.what = 2; mWorkerHandler.sendMessage(msgObj); } } } public classWorkerHandler extends Handler { private int value = 0; public WorkerHandler(Looperlooper) { super(looper); } @Override public voidhandleMessage(Message msg) { if (msg.what == 2) { doFakeWork(); if (value == 10) value = 0; MessagemsgObj = mUIHandler.obtainMessage(); msgObj.what = 1; Bundle b = new Bundle(); b.putInt("value", value++); msgObj.setData(b); mUIHandler.sendMessage(msgObj); } } } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。