黑马程序员技术交流社区

标题: 线程还没有发完 [打印本页]

作者: 我是刘通    时间: 2015-10-16 19:45
标题: 线程还没有发完
51.    }  
运行结果:

这出现了安全问题,需加入同步,输入和输出都需要加,注意保证线程都用同一把锁进行同步
[java] view plaincopy  
1.    class Input implements Runnable{  
2.        private Res r;  
3.        Input(Res r){  
4.            this.r = r;  
5.        }  
6.        public void run(){  
7.            int flag = 0;  
8.            while(true){  
9.                synchronized(r){  
10.                    if(flag==0){  
11.                        r.name = "张三";  
12.                        r.sex = "男";  
13.                    }else{  
14.                        r.name = "李四";  
15.                        r.sex = "女";  
16.                    }  
17.                }  
18.                flag = (flag+1)%2;//交替打印  
19.            }  
20.        }  
21.    }  
22.      
23.    class Output implements Runnable{  
24.        private Res r;  
25.        Output(Res r){  
26.            this.r = r;  
27.        }  
28.        public void run(){  
29.            while(true){  
30.                synchronized(r){  
31.                    System.out.println(r.name+"..."+r.sex);  
32.                }  
33.            }  
34.        }  
35.    }  
等待唤醒机制
多个线程操作共享数据时,保证数据交替被线程操作(比如输入一个数据,就输出一个数据的情况),则使用等待唤醒机制
wait();//该方法让线程进入线程池等待
notify();//该方法唤醒线程池中第一个等待的共有同一把锁的线程,该机制会导致出现生产者消费者问题(多个生产者和消费者的时候)
notifyAll();//该方法唤醒所有共有同一把锁的等待线程
都使用在同步代码中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义在Object类中?
因为这些方法在操作同步中的线程时,都必须要标示他们所操作线程持有的锁,只有同一个锁上的被等待线程可以被同一个notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
关键代码:
[java] view plaincopy  
1.    class Res  
2.    {  
3.        String name;  
4.        String sex;  
5.        boolean flag = false;//设置标记,判断资源状态,默认为假,表示资源为空。  
6.    }  
7.      
8.    class Input implements Runnable  
9.    {  
10.        private Res r ;  
11.        Input(Res r)  
12.        {  
13.            this.r = r;  
14.        }  
15.        public void run()  
16.        {  
17.            int x = 0;  
18.            while(true)  
19.            {  
20.                synchronized(r)  
21.                {  
22.      
23.                    if(r.flag)  
24.                        try{r.wait();}catch(Exception e){}//如果flag为真,表示资源存在,则使输入线程等待,r.wait()表示等待持有r这个锁的线程  
25.                    if(x==0)  
26.                    {  
27.                        r.name="张三";  
28.                        r.sex="男";  
29.                    }  
30.                    else  
31.                    {  
32.                        r.name="李四";  
33.                        r.sex = "女";  
34.                    }  
35.                    x = (x+1)%2;  
36.                    r.flag = true;//改变资源状态的标记  
37.                    r.notify();//唤醒共用该锁的第一个其他线程  
38.                }  
39.            }  
40.        }  
41.    }  
42.      
43.    class Output implements Runnable  
44.    {  
45.        private Res r ;  
46.         
47.        Output(Res r)  
48.        {  
49.            this.r = r;  
50.        }  
51.        public void run()  
52.        {  
53.            while(true)  
54.            {  
55.                synchronized(r)  
56.                {  
57.                    if(!r.flag)  
58.                        try{r.wait();}catch(Exception e){}  
59.                    System.out.println(r.name+"...."+r.sex);  
60.                    r.flag = false;  
61.                    r.notify();  
62.                }  
63.            }  
64.        }  
65.    }  
66.      
67.    class  InputOutputDemo  
68.    {  
69.        public static void main(String[] args)   
70.        {  
71.            Res r = new Res();  
72.      
73.            Input in = new Input(r);  
74.            Output out = new Output(r);  
75.      
76.            Thread t1 = new Thread(in);  
77.            Thread t2 = new Thread(out);  
78.      
79.            t1.start();  
80.            t2.start();  
81.        }  
82.    }  
或者将代码优化为(使用同步函数)
[java] view plaincopy  
1.    class Res  
2.    {  
3.        private String name;  
4.        private String sex;  
5.        private boolean flag = false;  
6.      
7.        public synchronized void set(String name,String sex)  
8.        {  
9.            if(flag)  
10.                try{this.wait();}catch(Exception e){}  
11.            this.name = name;  
12.              
13.            this.sex = sex;  
14.            flag = true;  
15.            this.notify();  
16.        }  
17.        public synchronized void out()  
18.        {  
19.            if(!flag)  
20.                try{this.wait();}catch(Exception e){}  
21.            System.out.println(name+"........"+sex);  
22.            flag = false;  
23.            this.notify();  
24.        }  
25.    }  
26.      
27.    class Input implements Runnable  
28.    {  
29.        private Res r ;  
30.        Input(Res r)  
31.        {  
32.            this.r = r;  
33.        }  
34.        public void run()  
35.        {  
36.            int x = 0;  
37.            while(true)  
38.            {  
39.                if(x==0)                  
40.                    r.set("张三","男");                  
41.                else      
42.                    r.set("李四","女");                  
43.                x = (x+1)%2;  
44.            }  
45.        }  
46.    }  
47.      
48.    class Output implements Runnable  
49.    {  
50.        private Res r ;  
51.         
52.        Output(Res r)  
53.        {  
54.            this.r = r;  
55.        }  
56.        public void run()  
57.        {  
58.            while(true)  
59.            {  
60.                r.out();  
61.            }  
62.        }  
63.    }  
64.      
65.    class  InputOutputDemo2  
66.    {  
67.        public static void main(String[] args)   
68.        {  
69.            Res r = new Res();  
70.      
71.            new Thread(new Input(r)).start();  
72.            new Thread(new Output(r)).start();  
73.        }  
74.    }  






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2