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 对应20ChunGe对于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