1.多个对之间的线程通信:多个线程的通信,要在每一次被唤醒之后,重新判断状态,再执行。而while+notify可能产生死锁,当唤醒的线程是本方的线程,判断之后,依然处于wait,一直没有去唤醒对方线程,导致所有线程都处于wait,则产生死锁。多对多通信如下:
class Resource {
private int num;
private boolean flag;
public synchronized void inDemo() {
while (flag)
try {
Thread.sleep(100);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
num++;
System.out.println(
Thread.currentThread().getName()
+ "...inDemo....." + num);
flag = true;
notifyAll();
}
public synchronized void outDemo() {
while (!flag)
try {
Thread.sleep(100);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(
Thread.currentThread().getName()
+ "...outDemo....." + num);
flag = false;
notifyAll();
}
}
class InDemo implements Runnable {
private Resource r;
public InDemo(Resource r) {
this.r = r;
}
@Override
public void run() {
while (true)
r.inDemo();
}
}
class OutDemo implements Runnable {
private Resource r;
public OutDemo(Resource r) {
this.r = r;
}
@Override
public void run() {
while (true)
r.outDemo();
}
}
public class ThreadDemo {
public static void main(String[] args) {
Resource r = new Resource();
InDemo in = new InDemo(r);
OutDemo out = new OutDemo(r);
new Thread(in).start();
new Thread(in).start();
new Thread(in).start();
new Thread(out).start();
new Thread(out).start();
new Thread(out).start();
}
}
2.使用Lock接口与Condition接口修改上面的多对通信:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Resource {
private int num;
private boolean flag;
private Lock lock;
private Condition con;
public Resource() {
num = 1;
flag = false;
lock = new ReentrantLock();
con = lock.newCondition();
}
public void inDemo() {
lock.lock();
try {
while (flag)
try {
Thread.sleep(100);
con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "...inDemo....." + num++);
flag = true;
con.signalAll();
} finally {
lock.unlock();
}
}
public void outDemo() {
lock.lock();
try {
while (!flag)
try {
Thread.sleep(100);
con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "...outDemo....." + num);
flag = false;
con.signalAll();
} finally {
lock.unlock();
}
}
}
class InDemo implements Runnable {
private Resource r;
public InDemo(Resource r) {
this.r = r;
}
@Override
public void run() {
while (true)
r.inDemo();
}
}
class OutDemo implements Runnable {
private Resource r;
public OutDemo(Resource r) {
this.r = r;
}
@Override
public void run() {
while (true)
r.outDemo();
}
}
public class ThreadDemo {
public static void main(String[] args) {
Resource r = new Resource();
InDemo in = new InDemo(r);
OutDemo out = new OutDemo(r);
new Thread(in).start();
new Thread(in).start();
new Thread(in).start();
new Thread(out).start();
new Thread(out).start();
new Thread(out).start();
}
}
3.使用同一锁Lock类产生的对象产生两个不同的Condition对象来等待/唤醒对应线程,解决了while-signal产生的死锁问题,两个Condition对象使得线程直接去唤醒需要唤醒的对应的正确的线程,也便不需要唤醒所有的线程,即不需要使用signalAll()方法。关键代码如下:
class Resource {
private int num;
private boolean flag;
private Lock lock;
private Condition in_Con;
private Condition out_Con;
public Resource() {
num = 1;
flag = false;
lock = new ReentrantLock();
//分组监视不同的状态,便于唤醒
in_Con = lock.newCondition();
out_Con = lock.newCondition();
}
public void inDemo() {
lock.lock();
try {
while (flag)
try {
Thread.sleep(100);
in_Con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "...inDemo....." + num++);
flag = true;
out_Con.signal();
} finally {
lock.unlock();
}
}
public void outDemo() {
lock.lock();
try {
while (!flag)
try {
Thread.sleep(100);
out_Con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "...outDemo....." + num);
flag = false;
in_Con.signal();
} finally {
lock.unlock();
}
}
}
4.利用数组解决生产者-消费者问题:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ArrRes {
// 被存储/读取数组
private int[] arr;
// 记录存储位置/读取位置/数组大小
private int inNum, outNum, count;
// 锁
private Lock lock;
// 双开监视
private Condition in_Con, out_Con;
//构造函数
public ArrRes() {
inNum = 0;
outNum = -1;
arr = new int[100];
count = arr.length;
lock = new ReentrantLock();
in_Con = lock.newCondition();
out_Con = lock.newCondition();
}
// 存储
public void in_Demo() throws InterruptedException {
lock.lock();
try {
while (inNum == count) {
Thread.sleep(100);
in_Con.await();
}
Thread.sleep(20);
arr[inNum] = inNum * inNum;
System.out.println(Thread.currentThread().getName() + "--------"
+ "已存储数组第" + inNum + "位:\t" + arr[inNum]);
outNum++;
inNum++;
out_Con.signal();
} finally {
lock.unlock();
}
}
// 读取
public void out_Demo() throws InterruptedException {
lock.lock();
try {
while (outNum < 0) {
Thread.sleep(8);
out_Con.await();
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + "读取到数组第"
+ outNum + "位\t" + arr[outNum]);
outNum--;
inNum--;
in_Con.signal();
} finally {
lock.unlock();
}
}
}
// 存储线程
class In_Thread implements Runnable {
private ArrRes r;
public In_Thread(ArrRes r) {
this.r = r;
}
@Override
public void run() {
while (true)
try {
r.in_Demo();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 读取线程
class Out_Thread implements Runnable {
private ArrRes r;
public Out_Thread(ArrRes r) {
this.r = r;
}
@Override
public void run() {
while (true)
try {
r.out_Demo();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 测试类
public class ThreadDemo {
public static void main(String[] args) {
ArrRes r = new ArrRes();
In_Thread in = new In_Thread(r);
Out_Thread out = new Out_Thread(r);
new Thread(in).start();
new Thread(in).start();
new Thread(in).start();
new Thread(out).start();
new Thread(out).start();
}
}
5.停止线程:线程如果处于运行状态,可以通过读取标志位,条件控制的方法来处理程序,使得线程终止。而线程处于冻结状态,无法读取标记,可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中,让线程具备CPU执行资格,而此时可以在发生的InterruptedException中处理更改状态,然后转向状态判断退出。以下示例:
public class ThreadDemo implements Runnable {
private boolean flag = true;
@Override
public synchronized void run() {
while (flag) {
try {
wait();
} catch (InterruptedException e) {
flag = false;
}
}
}
public void setFlag() {
this.flag = false;
}
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
Thread t1 = new Thread(td);
Thread t2 = new Thread(td);
Thread t3 = new Thread(td);
t1.start();
t2.start();
t3.start();
int num = 0;
while (num < 1000) {
num++;
if (num == 100) {
System.out.println(t1.getState());
t1.interrupt();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
System.out.println(t1.getState());
t2.interrupt();
System.out.println(t2.getState());
}
if (num == 200) {
System.out.println(t2.getState());
t3.interrupt();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
System.out.println(t2.getState());
if(Thread.State.TERMINATED == t3.getState())
System.out.println("t3 is ended");
}
}
}
}
6.守护线程,必须先定义,然后再启动。
ThreadDemo td = new ThreadDemo();
td.setDaemon(true);
td.start();
7.线程申请加入,使用join()方法,会停止当前线程,转而执行申请线程。setPriority(int n)参数从1到10,只是代表抢到CPU执行权的概率,而不是必然会得到。yield(),停止执行当前线程,执行其它线程。toString(),返回线程名,优先级,线程组。
———线程总结完毕———