zoukankan      html  css  js  c++  java
  • java多线程很好的一个实例

        java中的多线程 在java中要想实现多线程�有两种手段�一种是继续Thread类�另外一种是实现Runable接口。

    对于直接继承Thread的类来说�代码大致框架是� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    class 类名extends Thread{

    方法1;

    方法2�



    public void run(){

    // other code…

    }

    属性1�

    属性2�



     

    }

     先看一个简单的例子� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    /**

     * @author Rollen-Holt 继承Thread类,直接调用run方法

     * */

    class helloextends Thread {

     

        public hello() {

     

        }

     

        public hello(String name) {

            this.name = name;

        }

     

        public void run() {

            for (int i =0; i <5; i++) {

                System.out.println(name +"运行     " + i);

            }

        }

     

        public static void main(String[] args) { 5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    5

    2

    6

    2

    7

    2

    8

            hello h1=new hello("A");

            hello h2=new hello("B");

            h1.run();

            h2.run();

        }

     

        private String name;

    }

     【运行结果】� A运行     0 A运行     1 A运行     2 A运行     3 A运行     4 B运行     0 B运行     1 B运行     2 B运行     3 B运行     4 我们会发现这些都是顺序执行的�说明我们的调用方法不对�应该调用的是start��方法。

    当我们把上面的主函数修改为如下所示的时候� ?

    1

    2

    3

    4

    5

    6

    public static void main(String[] args) {

            hello h1=new hello("A");

            hello h2=new hello("B");

            h1.start();

            h2.start();

        }

     然后运行程序�输出的可能的结果如下� A运行     0 B运行     0 B运行     1 B运行     2 B运行     3 B运行     4 A运行     1 A运行     2 A运行     3 A运行     4

    因为需要用到CPU的资源�所以每次的运行结果基本是都不一样的�呵呵。

    注意�虽然我们在这里调用的是start��方法�但是实际上调用的还是run��方法的主体。

    那么�为什么我们不能直接调用run��方法呢�

    我的理解是�线程的运行需要本地操作系统的支持。

    如果你查看start的源代码的时候�会发现� ?

    1

    2

    3

    4

    5

    6

    7

    public synchronized void start() {

            /**

         * This method is not invoked for the main method thread or "system"

         * group threads created/set up by the VM. Any new functionality added

         * to this method in the future may have to also be added to the VM.

         *

         * A zero status value corresponds to state "NEW". 8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

             */

            if (threadStatus !=0 ||this != me)

                throw new IllegalThreadStateException();

            group.add(this);

            start0();

            if (stopBeforeStart) {

            stop0(throwableFromStop);

        }

    }

    private native void start0();

     注意我用红色加粗的那一条语句�说明此处调用的是start0��。并且这个这个方法用了native

    关键字�次关键字表示调用本地操作系统的函数。因为多线程的实现需要本地操作系统的支持。

    但是start方法重复调用的话�会出现java.lang.IllegalThreadStateException异常。 通过实现Runnable接口�

     

    大致框架是� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    class 类名implements Runnable{

    方法1;

    方法2�



    public void run(){

    // other code…

    }

    属性1�

    属性2�



     

    }

       来先看一个小例子吧� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    /**

     * @author Rollen-Holt 实现Runnable接口

     * */

    class helloimplements Runnable {

     

        public hello() {

     

        }

     

        public hello(String name) {

            this.name = name;

        }

     

        public void run() {

            for (int i =0; i <5; i++) {

                System.out.println(name +"运行     " + i);

            }

        }

     

        public static void main(String[] args) {

            hello h1=new hello("线程A");

            Thread demo=new Thread(h1);

            hello h2=new hello("线程�");

            Thread demo1=new Thread(h2);

            demo.start();

            demo1.start();

        }

     

        private String name;

    }

     5

    2

    6

    2

    7

    2

    8

    2

    9

    3

    0 【可能的运行结果】� 线程A运行     0 线程�运行     0 线程�运行     1 线程�运行     2 线程�运行     3 线程�运行     4 线程A运行     1 线程A运行     2 线程A运行     3 线程A运行     4

     

    关于选择继承Thread还是实现Runnable接口�

    其实Thread也是实现Runnable接口的� ?

    1

    2

    3

    4

    5

    6

    7

    8

    class Threadimplements Runnable {

        //…

    public void run() {

            if (target !=null) {

                 target.run();

            }

            }

    }

     其实Thread中的run方法调用的是Runnable接口的run方法。不知道大家发现没有�Thread和Runnable都实现了run方法�这种操作模式其实就是代理模式。关于代理模式�我曾经写过一个小例子呵呵�大家

    有 兴 趣 的 话 可 以 看 一 下 �http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144847.html

    Thread和Runnable的区别�

    如果一个类继承Thread�则不适合资源共享。但是如果实现了Runable接口的话�则很容易的

    实现资源共享。 ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    /**

     * @author Rollen-Holt 继承Thread类�不能资源共享

     * */

    class helloextends Thread {

        public void run() {

            for (int i =0; i <7; i++) {

                if (count >0) {

                    System.out.println("count= " + count--);

                }

            }

        }

     

        public static void main(String[] args) {

            hello h1 =new hello();

            hello h2 =new hello();

            hello h3 =new hello();

            h1.start();

            h2.start();

            h3.start();

        }

     

        private int count =5;

    }

     2

    3

      【运行结果】� count= 5 count= 4 count= 3 count= 2 count= 1 count= 5 count= 4 count= 3 count= 2 count= 1 count= 5 count= 4 count= 3 count= 2 count= 1

    大家可以想象�如果这个是一个买票系统的话�如果count表示的是车票的数量的话�说明并没有

    实现资源的共享。

    我们换为Runnable接口

      ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    class MyThreadimplements Runnable{

     

        private int ticket =5; //5张票

     

        public void run() {

            for (int i=0; i<=20; i++) {

                if (this.ticket >0) {

                    System.out.println(Thread.currentThread().getName()+"正在

    卖票"+this.ticket--); 1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

                }

            }

        }

    }

    public class lzwCode {

          

        public static void main(String [] args) {

            MyThread my =new MyThread();

            new Thread(my,"1号窗口").start();

            new Thread(my,"2号窗口").start();

            new Thread(my,"3号窗口").start();

        }

    }

              【运行结果】� count= 5 count= 4 count= 3 count= 2 count= 1

     

    总结一下吧�

    实现Runnable接口比继承Thread类所具有的优势� 1��适合多个相同的程序代码的线程去处理同一个资源

    2��可以避免java中的单继承的限制

    3��增加程序的健壮性�代码可以被多个线程共享�代码和数据独立。   

    所以�本人建议大家劲量实现接口。

    ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    /**

     * @author Rollen-Holt

     * 取得线程的名称

     * */

    class helloimplements Runnable {

        public void run() {

            for (int i =0; i <3; i++) {

                System.out.println(Thread.currentThread().getName());

            }

        }

     

        public static void main(String[] args) {

            hello he =new hello();

            new Thread(he,"A").start();

            new Thread(he,"B").start();

            new Thread(he).start();

        }

    }

     【运行结果】� A A A B B B Thread-0 Thread-0 Thread-0 说明如果我们没有指定名字的话�系统自动提供名字。 提醒一下大家�main方法其实也是一个线程。在java中所以的线程都是同时启动的�至于什么时候�哪

    个先执行�完全看谁先得到CPU的资源。

     

    在java中�每次程序运行至少启动2个线程。一个是main线程�一个是垃圾收集线程。因为每当

    使用java命令执行一个类的时候�实际上都会启动一个����每一个���实习在就是在操作系

    统中启动了一个进程。 判断线程是否启动 ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    /**

     * @author Rollen-Holt 判断线程是否启动

     * */

    class helloimplements Runnable {

        public void run() {

            for (int i =0; i <3; i++) {

                System.out.println(Thread.currentThread().getName());

            }

        }

     

        public static void main(String[] args) {

            hello he =new hello();

            Thread demo =new Thread(he);

            System.out.println("线程启动之前---》" + demo.isAlive());

            demo.start();

            System.out.println("线程启动之后---》" + demo.isAlive());

        }

    }

     1

    8 【运行结果】 线程启动之前---》false 线程启动之后---》true Thread-0 Thread-0 Thread-0 主线程也有可能在子线程结束之前结束。并且子线程不受影响�不会因为主线程的结束而结束。   

    线程的强制执行� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    /**

         * @author Rollen-Holt 线程的强制执行

         * */

        class helloimplements Runnable {

            public void run() {

                for (int i =0; i <3; i++) {

                    System.out.println(Thread.currentThread().getName());

                }

            }

          

            public static void main(String[] args) {

                hello he =new hello();

                Thread demo =new Thread(he,"线程");

                demo.start();

                for(int i=0;i<50;++i){

                    if(i>10){

                        try{

                            demo.join(); //强制执行demo

                        }catch (Exception e) {

                            e.printStackTrace();

                        }

                    }

                    System.out.println("main 线程执行-->"+i);

                }

            }

        }

     1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    5

    2

    6 【运行的结果】� main 线程执行-->0 main 线程执行-->1 main 线程执行-->2 main 线程执行-->3 main 线程执行-->4 main 线程执行-->5 main 线程执行-->6 main 线程执行-->7 main 线程执行-->8 main 线程执行-->9 main 线程执行-->10 线程 线程 线程 main 线程执行-->11 main 线程执行-->12 main 线程执行-->13 ���   

    线程的休眠� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    /**

     * @author Rollen-Holt 线程的休眠

     * */

    class helloimplements Runnable {

        public void run() {

            for (int i =0; i <3; i++) {

                try {

                    Thread.sleep(2000);

                }catch (Exception e) {

                    e.printStackTrace();

                }

                System.out.println(Thread.currentThread().getName() + i);

            }

        }

     

        public static void main(String[] args) {

            hello he =new hello();

            Thread demo =new Thread(he,"线程");

            demo.start();

        }

    }

     【运行结果】��结果每隔2s输出一个� 线程0 线程1 线程2   线程的中断� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    5

    /**

     * @author Rollen-Holt 线程的中断

     * */

    class helloimplements Runnable {

        public void run() {

            System.out.println("执行run方法");

            try {

                Thread.sleep(10000);

                System.out.println("线程完成休眠");

            }catch (Exception e) {

                System.out.println("休眠被打断");

                return; //返回到程序的调用处

            }

            System.out.println("线程正常终止");

        }

     

        public static void main(String[] args) {

            hello he =new hello();

            Thread demo =new Thread(he,"线程");

            demo.start();

            try{

                Thread.sleep(2000);

            }catch (Exception e) {

                e.printStackTrace();

            }

            demo.interrupt();//2s后中断线程

        }

    }

     2

    6

    2

    7

    2

    8 【运行结果】� 执行run方法 休眠被打断

     

    在java程序中�只要前台有一个线程在运行�整个java程序进程不会小时�所以此时可以设置一

    个后台线程�这样即使java进程小时了�此后台线程依然能够继续运行。 ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    /**

     * @author Rollen-Holt 后台线程

     * */

    class helloimplements Runnable {

        public void run() {

            while (true) {

                System.out.println(Thread.currentThread().getName() +"在运行

    ");

            }

        }

     

        public static void main(String[] args) {

            hello he =new hello();

            Thread demo =new Thread(he,"线程");

            demo.setDaemon(true);

            demo.start();

        }

    }

     虽然有一个死循环�但是程序还是可以执行完的。因为在死循环中的线程操作已经设置为后台运行了。 线程的优先级� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    /**

     * @author Rollen-Holt 线程的优先级

     * */

    class helloimplements Runnable {

        public void run() {

            for(int i=0;i<5;++i){

                System.out.println(Thread.currentThread().getName()+"运 行

    "+i);

            }

        }

     

        public static void main(String[] args) {

            Thread h1=new Thread(new hello(),"A");

            Thread h2=new Thread(new hello(),"B");

            Thread h3=new Thread(new hello(),"C");

            h1.setPriority(8);

            h2.setPriority(2);

            h3.setPriority(6);

            h1.start();

            h2.start();

            h3.start();

              

        }

    }

     

      【运行结果】� A运行0 A运行1 A运行2 A运行3 A运行4 B运行0 C运行0 C运行1 C运行2 C运行3 C运行4 B运行1 B运行2 B运行3 B运行4 。但是请读者不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源、   另外�主线程的优先级是5. 线程的礼让。 在线程操作中�也可以使用yield��方法�将一个线程的操作暂时交给其他线程执行。 ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    /**

     * @author Rollen-Holt 线程的优先级

     * */

    class helloimplements Runnable {

        public void run() {

            for(int i=0;i<5;++i){

                System.out.println(Thread.currentThread().getName()+"运 行

    "+i);

                if(i==3){

                    System.out.println("线程的礼让");

                    Thread.currentThread().yield();

                }

            }

        }

     

        public static void main(String[] args) { 3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

            Thread h1=new Thread(new hello(),"A");

            Thread h2=new Thread(new hello(),"B");

            h1.start();

            h2.start();

              

        }

    }

     A运行0 A运行1 A运行2 A运行3 线程的礼让 A运行4 B运行0 B运行1 B运行2 B运行3 线程的礼让 B运行4

     

     

    同步和死锁�

    【问题引出】:比如说对于买票系统�有下面的代码� ? 1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    5

    2

    6

    2

    /**

     * @author Rollen-Holt

     * */

    class helloimplements Runnable {

        public void run() {

            for(int i=0;i<10;++i){

                if(count>0){

                    try{

                        Thread.sleep(1000);

                    }catch(InterruptedException e){

                        e.printStackTrace();

                    }

                    System.out.println(count--);

                }

            }

        }

     

        public static void main(String[] args) {

            hello he=new hello();

            Thread h1=new Thread(he);

            Thread h2=new Thread(he);

            Thread h3=new Thread(he);

            h1.start();

            h2.start();

            h3.start();

        }

        private int count=5;

    }

     7

    2

    8 【运行结果】� 5 4 3 2 1 0 -1

    这里出现了-1�显然这个是错的。�应该票数不能为负值。

    如果想解决这种问题�就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行�

    其他的线程必须等到这个线程结束之后才能继续执行。

    【使用线程同步解决问题】

    采用同步的话�可以使用同步代码块和同步方法两种来完成。

     

    【同步代码块】�

    语法格式�

    synchronized�同步对象�{

     //需要同步的代码

    }

    但是一般都把当前对象this作为同步对象。

    比如对于上面的买票的问题�如下� ?

    1

    2

    3

    4

    5

    6

    7

    8

    /**

     * @author Rollen-Holt

     * */

    class helloimplements Runnable {

        public void run() {

            for(int i=0;i<10;++i){

                synchronized (this) {

                    if(count>0){ 9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    5

    2

    6

    2

    7

    2

    8

    2

    9

    3

    0

                        try{

                            Thread.sleep(1000);

                        }catch(InterruptedException e){

                            e.printStackTrace();

                        }

                        System.out.println(count--);

                    }

                }

            }

        }

     

        public static void main(String[] args) {

            hello he=new hello();

            Thread h1=new Thread(he);

            Thread h2=new Thread(he);

            Thread h3=new Thread(he);

            h1.start();

            h2.start();

            h3.start();

        }

        private int count=5;

    }

     【运行结果】��每一秒输出一个结果� 5 4 3 2 1

    【同步方法】

    也可以采用同步方法。

    语法格式为synchronized 方法返回类型方法名�参数列表�{     // 其他代码 } 现在�我们采用同步方法解决上面的问题。 ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    /**

     * @author Rollen-Holt

     * */

    class helloimplements Runnable {

        public void run() {

            for (int i =0; i <10; ++i) {

                sale();

            }

        }

     

        public synchronized void sale() {

            if (count >0) {

                try {

                    Thread.sleep(1000);

                }catch (InterruptedException e) {

                    e.printStackTrace();

                }

                System.out.println(count--);

            }

        }

     

        public static void main(String[] args) {

            hello he =new hello();

            Thread h1 =new Thread(he);

            Thread h2 =new Thread(he); 1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    5

    2

    6

    2

    7

    2

    8

    2

    9

    3

    0

    3

    1

    3

    2

    3

    3

            Thread h3 =new Thread(he);

            h1.start();

            h2.start();

            h3.start();

        }

     

        private int count =5;

    }

     【运行结果】�每秒输出一个� 5 4 3 2 1

    提醒一下�当多个线程共享一个资源的时候需要进行同步�但是过多的同步可能导致死锁。

    此处列举经典的生产者和消费者问题。 【生产者和消费者问题】

    先看一段有问题的代码。 ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    class Info {

     

        public String getName() {

            return name;

        }

     

        public void setName(String name) {

            this.name = name;

        }

     

        public int getAge() {

            return age;

        }

     

        public void setAge(int age) {

            this.age = age;

        }

     

        private String name ="Rollen";

        private int age =20;

    }

     

    /**

     * 生产者

     * */

    class Producerimplements Runnable{

        private Info info=null;

        Producer(Info info){

            this.info=info;

        }

          

        public void run(){

            boolean flag=false;

            for(int i=0;i<25;++i){

                if(flag){

                    this.info.setName("Rollen");

                    try{

                        Thread.sleep(100);

                    }catch (Exception e) {

                        e.printStackTrace(); 5

    2

    6

    2

    7

    2

    8

    2

    9

    3

    0

    3

    1

    3

    2

    3

    3

    3

    4

    3

    5

    3

    6

    3

    7

    3

    8

    3

    9

    4

    0

    4

    1

    4

    2

    4

    3

    4

    4

    4

    5

    4

    6

    4

                    }

                    this.info.setAge(20);

                    flag=false;

                }else{

                    this.info.setName("chunGe");

                    try{

                        Thread.sleep(100);

                    }catch (Exception e) {

                        e.printStackTrace();

                    }

                    this.info.setAge(100);

                    flag=true;

                }

            }

        }

    }

    /**

     * 消费者类

     * */

    class Consumerimplements Runnable{

        private Info info=null;

        public Consumer(Info info){

            this.info=info;

        }

          

        public void run(){

            for(int i=0;i<25;++i){

                try{

                    Thread.sleep(100);

                }catch (Exception e) {

                    e.printStackTrace();

                }

                

    System.out.println(this.info.getName()+"<---->"+this.info.getAge());

            }

        }

    }

     

    /**

     * 测试类

     * */

    class hello{

        public static void main(String[] args) {

            Info info=new Info(); 7

    4

    8

    4

    9

    5

    0

    5

    1

    5

    2

    5

    3

    5

    4

    5

    5

    5

    6

    5

    7

    5

    8

    5

    9

    6

    0

    6

    1

    6

    2

    6

    3

    6

    4

    6

    5

    6

    6

    6

    7

    6

    8

    6

            Producer pro=new Producer(info);

            Consumer con=new Consumer(info);

            new Thread(pro).start();

            new Thread(con).start();

        }

    }

     9

    7

    0

    7

    1

    7

    2

    7

    3

    7

    4

    7

    5

    7

    6

    7

    7

    7

    8

    7

    9

    8

    0

    8

    1

    8

    2

    8

    3

    8

    4

    8

    5

    8

    6

    8

    7

    8

    8

    8

    9 【运行结果】� Rollen<---->100 chunGe<---->20 chunGe<---->100 Rollen<---->100 chunGe<---->20 Rollen<---->100 Rollen<---->100 Rollen<---->100 chunGe<---->20 chunGe<---->20 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20 Rollen<---->100 chunGe<---->20

    大家可以从结果中看到�名字和年龄并没有对于。

     

    那么如何解决呢� 1�加入同步

    2�加入等待和唤醒 先来看看加入同步会是如何。 ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    5

    2

    6

    class Info {

          

        public String getName() {

            return name;

        }

     

        public void setName(String name) {

            this.name = name;

        }

     

        public int getAge() {

            return age;

        }

     

        public void setAge(int age) {

            this.age = age;

        }

     

        public synchronized void set(String name,int age){

            this.name=name;

            try{

                Thread.sleep(100);

            }catch (Exception e) {

                e.printStackTrace();

            }

            this.age=age;

        }

          

        public synchronized void get(){

            try{

                Thread.sleep(100);

            }catch (Exception e) {

                e.printStackTrace();

            }

            System.out.println(this.getName()+"<===>"+this.getAge());

        }

        private String name ="Rollen";

        private int age =20;

    }

     

    /**

     * 生产者

     * */ 2

    7

    2

    8

    2

    9

    3

    0

    3

    1

    3

    2

    3

    3

    3

    4

    3

    5

    3

    6

    3

    7

    3

    8

    3

    9

    4

    0

    4

    1

    4

    2

    4

    3

    4

    4

    4

    5

    4

    6

    4

    7

    4

    8

    class Producerimplements Runnable {

        private Info info =null;

     

        Producer(Info info) {

            this.info = info;

        }

     

        public void run() {

            boolean flag =false;

            for (int i =0; i <25; ++i) {

                if (flag) {

                      

                    this.info.set("Rollen",20);

                    flag =false;

                }else {

                    this.info.set("ChunGe",100);

                    flag =true;

                }

            }

        }

    }

     

    /**

     * 消费者类

     * */

    class Consumerimplements Runnable {

        private Info info =null;

     

        public Consumer(Info info) {

            this.info = info;

        }

     

        public void run() {

            for (int i =0; i <25; ++i) {

                try {

                    Thread.sleep(100);

                }catch (Exception e) {

                    e.printStackTrace();

                }

                this.info.get();

            }

        }

    }

      4

    9

    5

    0

    5

    1

    5

    2

    5

    3

    5

    4

    5

    5

    5

    6

    5

    7

    5

    8

    5

    9

    6

    0

    6

    1

    6

    2

    6

    3

    6

    4

    6

    5

    6

    6

    6

    7

    6

    8

    6

    9

    7

    0

    /**

     * 测试类

     * */

    class hello {

        public static void main(String[] args) {

            Info info =new Info();

            Producer pro =new Producer(info);

            Consumer con =new Consumer(info);

            new Thread(pro).start();

            new Thread(con).start();

        }

    }

     7

    1

    7

    2

    7

    3

    7

    4

    7

    5

    7

    6

    7

    7

    7

    8

    7

    9

    8

    0

    8

    1

    8

    2

    8

    3

    8

    4

    8

    5

    8

    6

    8

    7

    8

    8

    8

    9

    9

    0

    9

    1

    9

    2 9

    3

    9

    4

    9

    5

    9

    6

    9

    7

    9

    8

    9

    9 【运行结果】� Rollen<===>20 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 Rollen<===>20 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100 ChunGe<===>100

    从运行结果来看�错乱的问题解决了�现在是Rollen 对应20�ChunGe对于100

    �但是还是出现了重复读取的问题�也肯定有重复覆盖的问题。如果想解决这个问题�就需要使用

    Object类帮忙了、

    �我们可以使用其中的等待和唤醒操作。

    要完成上面的功能�我们只需要修改Info类饥渴�在其中加上标志位�并且通过判断标志位完成等

    待和唤醒的操作�代码如下� ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    class Info {

          

        public String getName() {

            return name;

        }

     

        public void setName(String name) {

            this.name = name;

        }

     

        public int getAge() {

            return age;

        }

     

        public void setAge(int age) {

            this.age = age;

        }

     

        public synchronized void set(String name,int age){

            if(!flag){

                try{

                    super.wait();

                }catch (Exception e) {

                    e.printStackTrace();

                }

            } 8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    2

    5

    2

    6

    2

    7

    2

    8

    2

    9

    3

    0

    3

    1

    3

    2

    3

    3

    3

    4

    3

    5

    3

    6

    3

    7

    3

    8

    3

    9

    4

            this.name=name;

            try{

                Thread.sleep(100);

            }catch (Exception e) {

                e.printStackTrace();

            }

            this.age=age;

            flag=false;

            super.notify();

        }

          

        public synchronized void get(){

            if(flag){

                try{

                    super.wait();

                }catch (Exception e) {

                    e.printStackTrace();

                }

            }

              

            try{

                Thread.sleep(100);

            }catch (Exception e) {

                e.printStackTrace();

            }

            System.out.println(this.getName()+"<===>"+this.getAge());

            flag=true;

            super.notify();

        }

        private String name ="Rollen";

        private int age =20;

        private boolean flag=false;

    }

     

    /**

     * 生产者

     * */

    class Producerimplements Runnable {

        private Info info =null;

     

        Producer(Info info) {

            this.info = info;

        }

      0

    4

    1

    4

    2

    4

    3

    4

    4

    4

    5

    4

    6

    4

    7

    4

    8

    4

    9

    5

    0

    5

    1

    5

    2

    5

    3

    5

    4

    5

    5

    5

    6

    5

    7

    5

    8

    5

    9

    6

    0

    6

    1

    6

        public void run() {

            boolean flag =false;

            for (int i =0; i <25; ++i) {

                if (flag) {

                      

                    this.info.set("Rollen",20);

                    flag =false;

                }else {

                    this.info.set("ChunGe",100);

                    flag =true;

                }

            }

        }

    }

     

    /**

     * 消费者类

     * */

    class Consumerimplements Runnable {

        private Info info =null;

     

        public Consumer(Info info) {

            this.info = info;

        }

     

        public void run() {

            for (int i =0; i <25; ++i) {

                try {

                    Thread.sleep(100);

                }catch (Exception e) {

                    e.printStackTrace();

                }

                this.info.get();

            }

        }

    }

     

    /**

     * 测试类

     * */

    class hello {

        public static void main(String[] args) {

            Info info =new Info();

            Producer pro =new Producer(info); 2

    6

    3

    6

    4

    6

    5

    6

    6

    6

    7

    6

    8

    6

    9

    7

    0

    7

    1

    7

    2

    7

    3

    7

    4

    7

    5

    7

    6

    7

    7

    7

    8

    7

    9

    8

    0

    8

    1

    8

    2

    8

    3

    8

            Consumer con =new Consumer(info);

            new Thread(pro).start();

            new Thread(con).start();

        }

    }

     4

    8

    5

    8

    6

    8

    7

    8

    8

    8

    9

    9

    0

    9

    1

    9

    2

    9

    3

    9

    4

    9

    5

    9

    6

    9

    7

    9

    8

    9

    9

    1

    0

    0

    1

    0

    1

    1

    0

    2

    1

    0

    3

    10

    4

    1

    0

    5

    1

    0

    6

    1

    0

    7

    1

    0

    8

    1

    0

    9

    1

    1

    0

    1

    1

    1

    1

    1

    2

    1

    1

    3

    1

    1

    4

    1

    1

    5

    1

    1

    6

    1

    1

    7

    1

    1

    8 1

    1

    9

    ?

    1

    2

    3

    4

    5

    6

    7

    8

    9

    1

    0

    1

    1

    1

    2

    1

    3

    1

    4

    1

    5

    1

    6

    1

    7

    1

    8

    1

    9

    2

    0

    2

    1

    2

    2

    2

    3

    2

    4

    【程序运行结果】�

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    ChunGe<===>100

    Rollen<===>20

    先在看结果就可以知道�之前的问题完全解决。

     2

    5

    2

    6

    2

    7

     

  • 相关阅读:
    HDU 2852 KiKi's K-Number (主席树)
    HDU 2089 不要62
    Light oj 1140 How Many Zeroes?
    Bless You Autocorrect!
    HDU 6201 transaction transaction transaction
    HDU1561 The more ,The better (树形背包Dp)
    CodeForces 607B zuma
    POJ 1651 Mulitiplication Puzzle
    CSUOJ 1952 合并石子
    Uva 1599 Ideal path
  • 原文地址:https://www.cnblogs.com/gtaxmjld/p/4225523.html
Copyright © 2011-2022 走看看