Java多线程总结(二)

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(),返回线程名,优先级,线程组。

———线程总结完毕———

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值