六、多线程的应用
1、线程间的通讯
/*
线程间通讯:
其实就是多个纯种在操作同一个资源,但是操作的动作不同。
*/
package day2;
class Res1
{
String name;
String sex;
boolean flag = false;
};
class Input1 implements Runnable
{
private Res1 r;
Input1(Res1 r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(r.flag)
try{r.wait();}catch (Exception e){}
if(x==0){
r.name="mike";
r.sex="man";
}else{
r.name="丽丽";
r.sex="美女";
}
x = (x+1)%2;
r.flag = true;
r.notify();
}
}
}
};
class Output1 implements Runnable
{
private Res1 r;
Output1(Res1 r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
if(!r.flag)
try{r.wait();}catch (Exception e){}
System.out.println(r.name+"..."+r.sex);
r.flag = false;
r.notify();
}
}
}
};
public class InputOutputDemo
{
public static void main(String[] args)
{
Res1 r = new Res1();
Input1 in = new Input1(r);
Output1 out = new Output1(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
2、JDK1.5中提供了多线程升级解决方案。
/*JDK1.5中提供了多线程升级解决方案。
* 将同步synchronized替换成显示的Lock操作。
* 将Object中的wait,natify,natifyAll,替换了Condition对象。
* 该对象可以Lock锁进行获取。
*
* 该示例中,实现了本方只唤醒对方操作。
* */
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Res
{
String name;
String sex;
boolean flag = false;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void set(String name,String sex)
{
lock.lock();
while(flag)
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.sex = sex;
this.name = name;
flag = true;
condition.signal();
lock.unlock();
}
public void get()
{
lock.lock();
while(!flag)
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"........"+sex);
flag = false;
condition.signal();
lock.unlock();
}
};
class Input implements Runnable
{
private Res r;
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
if(x==0)
r.set("mike","man");
else
r.set("丽丽","美女");
x = (x+1)%2;
}
}
};
class Output implements Runnable
{
private Res r;
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.get();
}
}
};
public class InputOutputDemo2
{
public static void main(String[] args)
{
Res r = new Res();
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
}
}
3、(1)如何停止线程?(2)冻结:changeFlag();(3)解除冻结:interrupt();(4)守护(后台线程)线程:setDaemon
/*
* 如何停止线程?
* 只有一种,run方法结束。
* 开启多线程运行,运行代码通常是循环结构。
*
* 只要控制信循环,就可以让run方法结束,也就是纯种结束。
*
* 冻结:changeFlag();
* 特殊情况:如下例子没了interrupt()和对应在异常中处理
* 当线程处于了冻结状态。
* 就不会讲到到标记,那么线程就不会结束。
*
*
* 解除冻结:interrupt();会产生异常
* 当没有指定的方式让冻结的线程恢复到运行状态时,这里需要对冻结进行清除。
* 强制让线程恢复到运行状态来,这样就可以操作标记让线程结束。
*
* 守护(后台线程)线程:setDaemon
* 开启后和主线程是同一级别,但它却依赖于主线程,所以不用去关闭它,只要主线程结束了它就自动结束。
* 如下例子不用去关闭标记为setDaemon的线程,主线程结束了,它也活不成了。
*
* */
class StopThread implements Runnable{
private boolean flag = true;
public synchronized void run(){
while(flag)
try{
wait();
}catch(InterruptedException e)
{
System.out.println(Thread.currentThread().getName()+"...Exception");
flag = false;
}
System.out.println(Thread.currentThread().getName()+"...run");
}
public void changeFlag()
{
flag = false;
}
}
public class SropThreadDemo {
public static void main(String[] args){
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
int num = 0;
while(true){
if(num++==60){
st.changeFlag();//冻结线程
//解除冻结让线程回到运行状态
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"...."+num);
}
System.out.println("....over");
}
}
4、等待线程:join();
/*
* 等待线程:Join(); 会产生异常
* 当A线程执行到了B线程的join()方法时,A就会等待,等 B线程执行完,Aft会执行。
*
* join可以用来临时加入线程执行。
*
* 下例子中把join()放到t2线程后面,t2是不会受到影响,因为join()只作用当前线程。
* */
class Demo implements Runnable{
public void run(){
for(int x=0;x<70;x++)
System.out.println(Thread.currentThread().getName()+"...."+x);
}
}
public class JoinDemo {
public static void main(String[] args) {
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.currentThread().setName("主线程");
for(int x=0;x<60;x++)
System.out.println(Thread.currentThread().getName()+"...."+x);
System.out.println("over");
}
}