Java多线程示例(模拟通话,sleep,join,yield,wait,notify,Semaphore)

线程基本控制方法

主线程等待子线程的多种方法
synchronized浅析
sleep 是静态方法,Thread.sleep(xx)谁调用谁睡眠。
join 是合并方法,当前线程调用其他线程xx.join()则等到xx结束才能运行
yield 当前线程让出cpu进入就绪队列。
wait,noitfy,synchronized配合使用对资源进行管理。

synchronized(this)以及非static的synchronized方法(至于static synchronized方法请往下看),只能防止多个线程同时执行同一个对象的同步代码段

Sleep

package cn.galc.test;

import java.util.*;

public class TestThread3 {
    public static void main(String args[]){
        MyThread thread = new MyThread();
        thread.start();//调用start()方法启动新开辟的线程
        try {
            /*Thread.sleep(10000);
            sleep()方法是在Thread类里面声明的一个静态方法,因此可以使用Thread.sleep()的格式进行调用
            */
            /*MyThread.sleep(10000);
            MyThread类继承了Thread类,自然也继承了sleep()方法,所以也可以使用MyThread.sleep()的格式进行调用
            */
            /*静态方法的调用可以直接使用“类名.静态方法名”
              或者“对象的引用.静态方法名”的方式来调用*/
            MyThread.sleep(10000);
            System.out.println("主线程睡眠了10秒种后再次启动了");
            //在main()方法里面调用另外一个类的静态方法时,需要使用“静态方法所在的类.静态方法名”这种方式来调用
            /*
            所以这里是让主线程睡眠10秒种
            在哪个线程里面调用了sleep()方法就让哪个线程睡眠,所以现在是主线程睡眠了。
            */
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //thread.interrupt();//使用interrupt()方法去结束掉一个线程的执行并不是一个很好的做法
        thread.flag=false;//改变循环条件,结束死循环
        /**
         * 当发生InterruptedException时,直接把循环的条件设置为false即可退出死循环,
         * 继而结束掉子线程的执行,这是一种比较好的结束子线程的做法
         */
        /**
         * 调用interrupt()方法把正在运行的线程打断
        相当于是主线程一盆凉水泼上去把正在执行分线程打断了
        分线程被打断之后就会抛InterruptedException异常,这样就会执行return语句返回,结束掉线程的执行
        所以这里的分线程在执行完10秒钟之后就结束掉了线程的执行
         */
    }
}

class MyThread extends Thread {
    boolean flag = true;// 定义一个标记,用来控制循环的条件

    public void run() {
        /*
         * 注意:这里不能在run()方法的后面直接写throw Exception来抛异常, 
         * 因为现在是要重写从Thread类继承而来的run()方法,重写方法不能抛出比被重写的方法的不同的异常。
         *  所以这里只能写try……catch()来捕获异常
         */
        while (flag) {
            System.out.println("==========" + new Date().toLocaleString() + "===========");
            try {
                /*
                 * 静态方法的调用格式一般为“类名.方法名”的格式去调用 在本类中声明的静态方法时调用时直接写静态方法名即可。 当然使用“类名.方法名”的格式去调用也是没有错的
                 */
                // MyThread.sleep(1000);//使用“类名.方法名”的格式去调用属于本类的静态方法
                sleep(1000);//睡眠的时如果被打断就会抛出InterruptedException异常
                // 这里是让这个新开辟的线程每隔一秒睡眠一次,然后睡眠一秒钟后再次启动该线程
                // 这里在一个死循环里面每隔一秒启动一次线程,每个一秒打印出当前的系统时间
            } catch (InterruptedException e) {
                /*
                 * 睡眠的时一盘冷水泼过来就有可能会打断睡眠 
                 * 因此让正在运行线程被一些意外的原因中断的时候有可能会抛被打扰中断(InterruptedException)的异常
                 */
                return;
                // 线程被中断后就返回,相当于是结束线程
            }
        }
    }
}

join

package cn.galc.test;

public class TestThread4 {
    public static void main(String args[]) {
        MyThread2 thread2 = new MyThread2("mythread");
        // 在创建一个新的线程对象的同时给这个线程对象命名为mythread
        thread2.start();// 启动线程
        try {
            thread2.join();// 调用join()方法合并线程,将子线程mythread合并到主线程里面
            // 合并线程后,程序的执行的过程就相当于是方法的调用的执行过程
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i <= 5; i++) {
            System.out.println("I am main Thread");
        }
    }
}

class MyThread2 extends Thread {
    MyThread2(String s) {
        super(s);
        /*
         * 使用super关键字调用父类的构造方法 
         * 父类Thread的其中一个构造方法:“public Thread(String name)” 
         * 通过这样的构造方法可以给新开辟的线程命名,便于管理线程
         */
    }

    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println("I am a\t" + getName());
            // 使用父类Thread里面定义的
            //public final String getName(),Returns this thread's name.
            try {
                sleep(1000);// 让子线程每执行一次就睡眠1秒钟
            } catch (InterruptedException e) {
                return;
            }
        }
    }
}

yield

package cn.galc.test;

public class TestThread5 {
    public static void main(String args[]) {
        MyThread3 t1 = new MyThread3("t1");
        /* 同时开辟了两条子线程t1和t2,t1和t2执行的都是run()方法 */
        /* 这个程序的执行过程中总共有3个线程在并行执行,分别为子线程t1和t2以及主线程 */
        MyThread3 t2 = new MyThread3("t2");
        t1.start();// 启动子线程t1
        t2.start();// 启动子线程t2
        for (int i = 0; i <= 5; i++) {
            System.out.println("I am main Thread");
        }
    }
}

class MyThread3 extends Thread {
    MyThread3(String s) {
        super(s);
    }

    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(getName() + ":" + i);
            if (i % 2 == 0) {
                yield();// 当执行到i能被2整除时当前执行的线程就让出来让另一个在执行run()方法的线程来优先执行
                /*
                 * 在程序的运行的过程中可以看到,
                 * 线程t1执行到(i%2==0)次时就会让出线程让t2线程来优先执行 
                 * 而线程t2执行到(i%2==0)次时也会让出线程给t1线程优先执行
                 */
            }
        }
    }
}

生产者消费者(wait,notify)

import java.util.Random;

public class TestAbstract{
    public static void main(String[] args) {
        Thread [] C = new Thread[5];
        Thread [] P = new Thread[5];
        Stack stk = new Stack();
        for(int i = 0;i<5;i++){
            P[i] = new Thread(new Proceduce(stk));
            P[i].setName("procedure "+i);
            P[i].start();
            C[i] = new Thread(new Consumer(stk));
            C[i].setName("Consumer "+i);
            C[i].start();
        }
    }
}

class Stack{
    String table = "abcdefghijklmnopqrstuvwxyz1234567890";
    private int cnt = 0;
    private char [] data = new char[10];
//  private Object cu = new Object();
//  private Object po = new Object();
    public synchronized void push(char ch){
        System.out.println(Thread.currentThread().getName()+" stack'cnt is "+cnt+"");
        while(cnt == data.length){
            try {
                System.out.println(Thread.currentThread().getName()+" must wait");
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        data[cnt++] = ch;
        this.notify();
    }
    public synchronized char pop(){
        System.out.println(Thread.currentThread().getName()+" stack'cnt is "+cnt+"");
    while(cnt == 0){
            try {
                System.out.println(Thread.currentThread().getName()+" must wait");
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        this.notify();
        return data[--cnt];
    }
}
/**
 * 
 * @author Administrator
 *
 */
class Consumer implements Runnable{
    private Stack stk = null;
    public Consumer(Stack stk){
        this.stk = stk;
    }
    @Override
    public String toString() {
        return "Consumer [name=" + Thread.currentThread().getName() + "]";
    }
    public void run() {
        // TODO Auto-generated method stub
        for(int i = 0;i < 10;i++){
            try {
                System.out.println(Thread.currentThread().getName()+" get char "+stk.pop());
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
/**
 * 
 * @author Administrator
 *
 */

class Proceduce implements Runnable{
    private Stack stk = null;
    private Random rdm = new Random();
    public Proceduce(Stack stk) {
        super();
        this.stk = stk;
    }

    public void run() {
        // TODO Auto-generated method stub
        for(int i = 0;i < 10;i++){
            try {
                stk.push( stk.table.charAt( rdm.nextInt( stk.table.length() ) ) );
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

多线程拨号通话

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class TestAbstract{
    static String [] tele = null;
    public static void main(String[] args) throws Exception {
        System.out.println(System.getProperty("user.dir"));
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(".\\src\\tele.txt")));
        ArrayList<String> list = new ArrayList<String>();
        String tmp;
        while((tmp = br.readLine())!=null){
            list.add(tmp);
            System.out.println(tmp);
        }
        tele = (String [])list.toArray(new String[0]);
        for(String s:tele)
            System.out.println(s);
        list = null;
        br.close();
        //获取需要拨打的电话
        //创建10个线程工作
        ArrayList<Thread> tt = new ArrayList<Thread>();
        for(int i = 0;i<10;i++){
            Thread t = new Thread(new work());
            t.setName("Thread "+(i+1));
            t.start();
            tt.add(t);
        }
        for(Thread t:tt){
            t.join();
        }

        System.out.println("dial is done");
    }
}
class work implements Runnable{
    static boolean [] tag = null;
    boolean flag;
    public work(){
        if(tag==null)//线程中止4种方法,这个最安全
            tag = new boolean[TestAbstract.tele.length];
        flag = true;
    }
    String dial(){
        synchronized (work.class) {
            for(int i = 0;i<tag.length;i++){
                if(tag[i]==false){
                    tag[i] = true;
                    return TestAbstract.tele[i];
                }
            }
        }
        return null;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(flag){
            String str = dial();
            if(str==null){
                flag = false;
                break;
            }
            System.out.println(Thread.currentThread().getName() + " start dial " + str);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " dial "+str+" success");
        }

    }

}

Semaphore
ref

public class asdf {

    public static void main(String[] args) {
        // 线程池
        ExecutorService exec = Executors.newCachedThreadPool();
        // 只能5个线程同时访问
        final Semaphore semp = new Semaphore(5);
        // 模拟20个客户端访问
        for (int index = 0; index < 20; index++) {

            final int NO = index;

            Runnable run = new Runnable() {
                public void run() {
                    try {
                        // 获取许可
                        semp.acquire();
                        System.out.println("Accessing: " + NO);
                        Thread.sleep((long) (Math.random() * 10000));
                        // 访问完后,释放
                        semp.release();
                        System.out.println("-----------------"+semp.availablePermits());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            exec.execute(run);
        }
        // 退出线程池
        exec.shutdown();
    }
}

测试整理

public class asdf {
    /**
     * 生产者消费者模型,通过对同一个对象操作来进行同步。
     * 生产者之间,消费者之间,生产消费者间互斥
     */
    static Object consumerObj = new Object();
    static Object providerObj = new Object();

    class Consumer implements Runnable {

        @Override public void run() {
            consumer();
        }

        void consumer() {
            System.out.println(Thread.currentThread().getName() + " start");
            // 对Data进行互斥 ,也可以进行Semaphore.require,release 或者Lock 或者AtomicBoolean
            synchronized (Data.data) {
                while (Data.data.isEmpty()) {
                    try {
                        System.out.println(
                            Thread.currentThread().getName() + " data is empty,wait seconds");
                        Data.data.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        Data.data.notifyAll();
                    }
                }
                System.out.println(
                    Thread.currentThread().getName() + " Consumer data:" + Data.data.poll());
                Data.data.notifyAll();
            }
            System.out.println(Thread.currentThread().getName() + " end");
        }
    }

    class Provider implements Runnable {
        @Override public void run() {
            provider();
        }

        void provider() {
            System.out.println(Thread.currentThread().getName() + " start");
            synchronized (Data.data) {
                while (Data.data.size() >= Data.dataLength) {
                    try {
                        System.out.println(
                            Thread.currentThread().getName() + " data is full,wait seconds");
                        Data.data.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        Data.data.notifyAll();
                    }
                }
                int d = (int) (Math.random() * 1000);
                Data.data.offer(d);
                System.out.println(Thread.currentThread().getName() + " Provider data:" + d);
                Data.data.notifyAll();
            }
            System.out.println(Thread.currentThread().getName() + " end");
        }
    }

    static class Data {
        static final Queue<Integer> data = new LinkedList<Integer>();
        static final int dataLength = 10;
    }

    static int wr;
    static int readCnt = 0;
    static int writeCnt = 0;
    Semaphore readerSemaphore = new Semaphore(1);
    Semaphore writerSemaphore = new Semaphore(1);
    Semaphore readCntSemaphore = new Semaphore(1);
    Semaphore writeCntSemaphore = new Semaphore(1);

    class Writer1 implements Runnable {
        void writer(int num) {
            try {
                writerSemaphore.acquire();
                wr = num;
                System.out.println(Thread.currentThread().getName() + " write num:" + num);
                Thread.sleep((long) (Math.random() * 1000));
                writerSemaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        @Override public void run() {
            writer((int) (Math.random() * 1000));
        }
    }

    class Reader1 implements Runnable {
        int reader() {
            int ret = 0;
            try {
                readerSemaphore.acquire();
                if (readCnt == 0)
                    writerSemaphore.acquire();  // 没有读者在读,则可能存在写者,因此在这里尝试获取锁
                readCnt++;
                readerSemaphore.release();

                ret = wr;
                System.out.println(Thread.currentThread().getName() + " read num:" + ret);
                Thread.sleep((long) (Math.random() * 1000));
                readerSemaphore.acquire();
                readCnt--;
                if (readCnt == 0)
                    writerSemaphore.release();
                readerSemaphore.release();
                return ret;
            } catch (InterruptedException e) {
                e.printStackTrace();
                return ret;
            }
        }

        @Override public void run() {
            reader();
        }
    }

    class Reader2 implements Runnable {
        public int reader() {
            int ret=0;
            try {
                readerSemaphore.acquire();
                readCntSemaphore.acquire();
                readCnt++;
                if(readCnt == 1){
                    writerSemaphore.acquire();
                }
                readCntSemaphore.release();
                readerSemaphore.release();

                ret = wr;
                System.out.println(Thread.currentThread().getName() + " read data:" + ret);
                Thread.sleep((long) (Math.random() * 1000));

                readCntSemaphore.acquire();
                readCnt--;
                if(readCnt == 0){
                    writerSemaphore.release();  // 读写互斥
                }
                readCntSemaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return ret;
        }
        @Override public void run() {
            reader();
        }
    }

    class Writer2 implements Runnable {

        public void writer(int num) {
            try {
                writeCntSemaphore.acquire();
                writeCnt++;
                if(writeCnt == 1){
                    readerSemaphore.acquire();  // 读写互斥
                }
                writeCntSemaphore.release();

                writerSemaphore.acquire();
                wr = num;
                System.out.println(Thread.currentThread().getName() + " write data:" + num);
                Thread.sleep((long) (Math.random() * 1000));

                writerSemaphore.release();

                writeCntSemaphore.acquire();
                writeCnt--;
                if(writeCnt == 0){
                    readerSemaphore.release();  // 读写互斥
                }
                writeCntSemaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        @Override public void run() {
            writer((int) (Math.random() * 1000));
        }
    }

    static void ProviderConsumerTest() {
        // 线程池
        ExecutorService exec = Executors.newCachedThreadPool();

        asdf tt = new asdf();
        for (int index = 0; index < 5; index++) {
            Thread t = new Thread(tt.new Consumer());
            t.setName("Consumer" + String.valueOf(index));
            exec.execute(t);
        }
        for (int index = 0; index < 5; index++) {
            Thread t = new Thread(tt.new Provider());
            t.setName("Provider" + String.valueOf(index));
            exec.execute(t);
        }
        // 退出线程池
        exec.shutdown();
    }

    static void readerPriority() {
        asdf tt = new asdf();
        Random random = new Random();
        random.setSeed(System.currentTimeMillis());
        for (int i = 0; i < 20; i++) {
            //随机生成读者和写者
            if (random.nextBoolean()) {
                Thread t = new Thread(tt.new Reader1());
                t.start();
            } else {
                Thread t = new Thread(tt.new Writer1());
                t.start();
            }
        }
    }
    static void writerPriority() {
        asdf tt = new asdf();
        Random random = new Random();
        random.setSeed(System.currentTimeMillis());
        for (int i = 0; i < 20; i++) {
            //随机生成读者和写者
            if (random.nextBoolean()) {
                Thread t = new Thread(tt.new Reader2());
                t.start();
            } else {
                Thread t = new Thread(tt.new Writer2());
                t.start();
            }
        }
    }
    public static void main(String[] args) {
        //        生产者消费者示例
        //        ProviderConsumerTest();
        //        读者优先
        //        readerPriority();
//        写者优先
        writerPriority();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值