java的线程问题同步与互斥
2014-08-07 23:21
387 查看
以前学过java的线程,但是当时对Tread的理解不是很深,对于里面的同步与互斥,生产者与消费者问题,理解的不够深入,这次又从新学习java的多线程,感觉对线程的理解更加的深入了,觉得有必要写下博客记录下。
本文原创,转载请著明:http://blog.csdn.net/j903829182/article/details/38420503
1.java实现线程的方法;
1.实现Runnable接口,重写run方法,通过Thread的start方法启动线程。这种方法可以实现资源的共享
2.继承Thread类,重写run方法
推荐使用Runnable接口实现多线程。
2.线程的状态
创建
开始
就绪
运行
阻塞
终止
3.线程控制的基本方法
isAlive判断线程是否还活着,即线程是否还未终止
getPriority获得线程的优先级数,数值。
setPriority设置线程的优先级数值
Thread.sleep将当前线程睡眠指定毫秒数
join调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行。
yield让出cpu,当前线程进入就绪等待调度
wait当前线程进入对象的wait pool
notify/notifyAll唤醒对象的wait pool中的一个/所有等待线程
4.wait和sleep的区别
wait时别的线程可以访问锁定对象,释放cpu的控制权,调用wait方法时必须锁定该对象
sleep时别的线程也不可以访问锁定对象。但可以释放cpu的控制权
5.在执行wait()和notify()之前,必须要先获得互斥锁,即一定要和synchronized一起使用
6.需要注意的是notify()/notifyAll()(唤醒在等待该对象同步锁的线程)调用后,并不是马上就释放对象锁的,
而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM才会在wait()对象锁的线程中随机选取一线程,
赋予其对象锁,唤醒线程,继续执行。
7.以下是我写的线程的一些例子,相信应该能够看懂,我就不多说了,有不理解的可以相互交流,共同进步。
生产者消费者的例子:
package com.wj.demo;
/*
class Info{
private String name="李新华";
private String content="java讲师";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
class Producer implements Runnable{
private Info info=null;
public Producer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean flag=false;
for(int i=0;i<50;i++){
if(flag){
this.info.setName("李兴华");
try {
Thread.sleep(90);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.setContent("java讲师");
flag=false;
}else{
this.info.setName("baidu");
try {
Thread.sleep(90);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.setContent("www.baidu.com");
flag=true;
}
}
}
}
class Consumer implements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.info.getName()+"--->"
+this.info.getContent());
}
}
}
*/
/*
class Info{
private String name="李新华";
private String content="java讲师";
public synchronized void set(String name,String content){
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.setContent(content);
}
public synchronized void get(){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.getName()+"-->"
+this.getContent());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
class Producer implements Runnable{
private Info info=null;
public Producer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean flag=false;
for(int i=0;i<50;i++){
if(flag){
this.info.set("李兴华","java讲师");
flag=false;
}else{
this.info.set("mldn", "www.mldn.com");
flag=true;
}
}
}
}
class Consumer implements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.get();
}
}
}
*/
/*
class Info{
private String name="李新华";
private String content="java讲师";
private boolean flag=false;
public synchronized void set(String name,String content){
if(!flag){
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.setContent(content);
flag=false;
super.notify();
}
public synchronized void get(){
if(flag){
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.getName()+"-->"
+this.getContent());
flag=true;
super.notify();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
class Producer implements Runnable{
private Info info=null;
public Producer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean flag=false;
for(int i=0;i<50;i++){
if(flag){
this.info.set("李兴华","java讲师");
flag=false;
}else{
this.info.set("mldn", "www.mldn.com");
flag=true;
}
}
}
}
class Consumer implements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.get();
}
}
}
*/
class Info{
private String name="张三";
//private String content="java讲师";
private boolean flag=false;
public synchronized void set(String name){
if(!flag){
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//this.setContent(content);
flag=false;
super.notify();
}
public synchronized void get(){
if(flag){
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.getName()+"-->"
);
flag=true;
super.notify();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/*public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}*/
}
class Producer implements Runnable{
private Info info=null;
public Producer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean flag=false;
for(int i=0;i<20;i++){
if(flag){
this.info.set("张三");
flag=false;
}else{
this.info.set("李四");
flag=true;
}
}
}
}
class Consumer implements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<20;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.get();
}
}
}
public class ThreadDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Info i=new Info();
Producer pro=new Producer(i);
Consumer con=new Consumer(i);
new Thread(pro).start();
new Thread(con).start();
}
}
下面是程序的输出结果:
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
从运行结果可以看到的是,生产者生产一个,消费者消费一个,进行同步输出
下面是我的写的一个买票的线程例子:
package com.wj.demo;
class MyThread1 extends Thread{
private String name;
public MyThread1(String name){
this.name=name;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
System.out.println(name+i);
}
}
}
class MyThread2 implements Runnable{
private String name;
public MyThread2(String name){
this.name=name;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
System.out.println(name+i);
}
}
}
class MyThread3 implements Runnable{
private int ticket=5;
@Override
public void run() {
// TODO Auto-generated method stub
if(ticket>0){
System.out.println("卖票:ticket="+ticket--);
}
}
}
class MyThread4 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+"运行,i="+i);
}
}
}
class MyThread5 implements Runnable{
private String name;
private int time;
public MyThread5(String name,int time){
this.name=name;
this.time=time;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(this.time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.name+"线程,休眠"+this.time+"毫秒");
}
}
class MyThread6 implements Runnable{
private int ticket=110;
/*private String name=null;
public MyThread6(String name){
this.name=name;
}*/
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<200;i++){
synchronized(this){
if(ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖票:ticket="+ticket--);
}
}
}
}
}
public class ThreadDemo1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//MyThread1 mt1=new MyThread1("线程A");
//MyThread1 mt2=new MyThread1("线程B");
//mt1.start();
//mt2.start();
/*
MyThread2 my1=new MyThread2("线程--A");
MyThread2 my2=new MyThread2("线程--B");
Thread th1=new Thread(my1);
Thread th2=new Thread(my2);
th1.start();
th2.start();*/
/*
MyThread3 my=new MyThread3();
new Thread(my).start();
new Thread(my).start();
new Thread(my).start();
new Thread(my).start();
new Thread(my).start();*/
/*
MyThread4 my=new MyThread4();
new Thread(my).start();
new Thread(my,"线程A").start();
new Thread(my,"线程B").start();
new Thread(my).start();
new Thread(my).start();*/
/*
MyThread5 my1=new MyThread5("线程A",10000);
MyThread5 my2=new MyThread5("线程B",20000);
MyThread5 my3=new MyThread5("线程C",30000);
MyThread5 my4=new MyThread5("线程D",40000);
new Thread(my1).start();
new Thread(my2).start();
new Thread(my3).start();
new Thread(my4).start();*/
MyThread6 mt=new MyThread6();
Thread t1=new Thread(mt,"A");
Thread t2=new Thread(mt,"B");
Thread t3=new Thread(mt,"C");
Thread t4=new Thread(mt,"D");
Thread t5=new Thread(mt,"E");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
程序的运行结果可能如下所示:
B卖票:ticket=110
B卖票:ticket=109
B卖票:ticket=108
B卖票:ticket=107
B卖票:ticket=106
B卖票:ticket=105
B卖票:ticket=104
B卖票:ticket=103
B卖票:ticket=102
B卖票:ticket=101
B卖票:ticket=100
B卖票:ticket=99
E卖票:ticket=98
E卖票:ticket=97
E卖票:ticket=96
E卖票:ticket=95
E卖票:ticket=94
E卖票:ticket=93
E卖票:ticket=92
E卖票:ticket=91
E卖票:ticket=90
E卖票:ticket=89
E卖票:ticket=88
E卖票:ticket=87
E卖票:ticket=86
E卖票:ticket=85
E卖票:ticket=84
E卖票:ticket=83
E卖票:ticket=82
E卖票:ticket=81
E卖票:ticket=80
E卖票:ticket=79
E卖票:ticket=78
E卖票:ticket=77
E卖票:ticket=76
D卖票:ticket=75
D卖票:ticket=74
D卖票:ticket=73
D卖票:ticket=72
C卖票:ticket=71
C卖票:ticket=70
C卖票:ticket=69
C卖票:ticket=68
C卖票:ticket=67
C卖票:ticket=66
C卖票:ticket=65
A卖票:ticket=64
A卖票:ticket=63
A卖票:ticket=62
C卖票:ticket=61
C卖票:ticket=60
C卖票:ticket=59
C卖票:ticket=58
C卖票:ticket=57
C卖票:ticket=56
C卖票:ticket=55
C卖票:ticket=54
C卖票:ticket=53
C卖票:ticket=52
C卖票:ticket=51
C卖票:ticket=50
D卖票:ticket=49
D卖票:ticket=48
D卖票:ticket=47
D卖票:ticket=46
D卖票:ticket=45
D卖票:ticket=44
D卖票:ticket=43
D卖票:ticket=42
D卖票:ticket=41
E卖票:ticket=40
E卖票:ticket=39
E卖票:ticket=38
E卖票:ticket=37
E卖票:ticket=36
E卖票:ticket=35
E卖票:ticket=34
E卖票:ticket=33
E卖票:ticket=32
E卖票:ticket=31
E卖票:ticket=30
E卖票:ticket=29
B卖票:ticket=28
B卖票:ticket=27
B卖票:ticket=26
B卖票:ticket=25
B卖票:ticket=24
B卖票:ticket=23
B卖票:ticket=22
B卖票:ticket=21
B卖票:ticket=20
B卖票:ticket=19
B卖票:ticket=18
B卖票:ticket=17
B卖票:ticket=16
B卖票:ticket=15
B卖票:ticket=14
E卖票:ticket=13
E卖票:ticket=12
D卖票:ticket=11
D卖票:ticket=10
D卖票:ticket=9
D卖票:ticket=8
D卖票:ticket=7
D卖票:ticket=6
D卖票:ticket=5
C卖票:ticket=4
C卖票:ticket=3
C卖票:ticket=2
C卖票:ticket=1
下面的程序展示的是,打印10次A,10次B,10次C,打印的顺序是ABCABCABC.......下面是用线程实现的代码。
代码里面的注释已经很清楚了,我就不再解释了,有问题的,欢迎一起交流,一起进步。
package com.wj.demo;
/*
* 1.Product类是一个产品类,用来表示生产产品
* 2.里面的有set和get方法,set方法用来设置生产什么样的产品,get是得到产品*/
class Product{
private String name="A";//产品的名字
private boolean flag=true;//标志,true代表可以生产,false代表可以取得产品
//注意:super.wait(),super.notifyAll()这2个方法,一定要是在synchronized所
//包含的代码块里面调用,也就是说只有拥有对象锁的线程,才能有权调用super.wait(),super.notifyAll()
//方法,否则会出错。之所以会这样,是因为super.wait()方法是把拥有该对象锁的线程放到等待该对象锁的队列中进行休息
//这个过程需要找到拥有对象锁的线程,所以super.wait()方法应该在synchronized里面的代码块中调用;
//同理,super.notifyAll()是用来唤醒在等待该对象锁队列中所有的线程,所以也需要和对象锁有关系,唤醒的是想得到
//该对象锁的所有线程,因此也需要在synchronized代码块中使用。
//synchronized表示只有拥有该对象锁的线程才能进入synchronized代码块,里面。
//综上所述,synchronized,super.wait(),super.notifyAll(),在进行同步控制的时候一般是需要一起配对使用
public synchronized void getName() {//得到产品的函数
if(flag){//如果标志为true,则代表只可以生产,不能进行取产品
try {
super.wait();//调用Object父类的方法,使得到该对象锁的线程等待,把该线程放到等待该对象锁的队列里面
//,并且释放cpu,和释放该对象的对象锁,使其他的线程可以得到该对象的锁
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(name);//打印产品的名字
try {
Thread.sleep(200);//该线程休眠200毫秒,释放cup,让其他的线程执行,但是不会释放对象锁
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
flag=true;//把标志置位true,表示已经取了产品了,可以进行生产了,已经不没有产品了,不能得到产品了
//调用了super.notifyAll()方法后,并不会马上执行,要等待synchronized代码块所有的程序执行完了以后才会
//释放对象锁,进行唤醒其他的线程
super.notifyAll();//调用父类Object的方法,释放对象锁,唤醒在等待该对象锁的所有线程
}
public synchronized void setName(String name) {
if(!flag){//如果flag为false则表示,只可以取产品,不能进行生产产品
try {
super.wait();//进行等待,和上面的一样
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(200);//解释如上
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.name = name;//设置产品的名字
flag=false;//设置标志,表示可以取产品了,不能再进行生产了
super.notifyAll();//如上所示,唤醒其他的想得到该对象锁的所有线程
}
}
//Factory类是一个工厂,用来控制生产什么样的产品
class Factory implements Runnable{
private Product product;//共享的对象
public Factory(Product product) {//构造函数,对product进行初始化
super();
this.product = product;
}
@Override
public void run() {//覆写的run方法,进行线程操作
// TODO Auto-generated method stub
for(int i=1;i<31;i++){
if(i%3==1){//如果余数为1,则生产A产品
product.setName("A");//生产A产品
}else if(i%3==2){//如果余数为2,则生产B产品
product.setName("B");//生产B产品
}else{//其他的生产C产品
product.setName("C");//生产C产品
}
}
}
}
//Customer是消费者类,用来使用工厂生产的产品
class Customer implements Runnable{
private Product product;//贡献资源对象
public Customer(Product product) {//构造函数,初始化product
super();
this.product = product;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=1;i<31;i++){
try {
Thread.sleep(500);//进行线程休眠,使打印有时间延迟
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(""+i+"----->");
this.product.getName();//消费产品
}
}
}
public class ThreadDemo4 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Product p=new Product();//创建共享资源对象
Factory fp=new Factory(p);//创建工厂
Customer cp=new Customer(p);//创建消费者
Thread tfp=new Thread(fp);//创建工厂线程进行生产
Thread tcp=new Thread(cp);//创建消费者线程进行消费
tfp.start();//启动线程
tcp.start();//启动线程
}
}
程序的运行结果如下:
1----->A
2----->B
3----->C
4----->A
5----->B
6----->C
7----->A
8----->B
9----->C
10----->A
11----->B
12----->C
13----->A
14----->B
15----->C
16----->A
17----->B
18----->C
19----->A
20----->B
21----->C
22----->A
23----->B
24----->C
25----->A
26----->B
27----->C
28----->A
29----->B
30----->C
到此线程的知识也就基本讲完了,发现对上面的知识进行总结以后,线程也就并没有那么难了,难得就是难于理解什么是多线程,多线程的运行过程。要是理解了多线程的运行过程,那么java中的线程也就没那么可怕了。最后一点就是要举义反三,融汇贯通,利用典型的生产者消费者模式,可以演变后解决很多线程的问题。希望好好理解生产者消费者模式。如果对线程还有什么问题,希望我们可以一起交流。
本文原创,转载请著明:http://blog.csdn.net/j903829182/article/details/38420503
1.java实现线程的方法;
1.实现Runnable接口,重写run方法,通过Thread的start方法启动线程。这种方法可以实现资源的共享
2.继承Thread类,重写run方法
推荐使用Runnable接口实现多线程。
2.线程的状态
创建
开始
就绪
运行
阻塞
终止
3.线程控制的基本方法
isAlive判断线程是否还活着,即线程是否还未终止
getPriority获得线程的优先级数,数值。
setPriority设置线程的优先级数值
Thread.sleep将当前线程睡眠指定毫秒数
join调用某线程的该方法,将当前线程与该线程“合并”,即等待该线程结束,再恢复当前线程的运行。
yield让出cpu,当前线程进入就绪等待调度
wait当前线程进入对象的wait pool
notify/notifyAll唤醒对象的wait pool中的一个/所有等待线程
4.wait和sleep的区别
wait时别的线程可以访问锁定对象,释放cpu的控制权,调用wait方法时必须锁定该对象
sleep时别的线程也不可以访问锁定对象。但可以释放cpu的控制权
5.在执行wait()和notify()之前,必须要先获得互斥锁,即一定要和synchronized一起使用
6.需要注意的是notify()/notifyAll()(唤醒在等待该对象同步锁的线程)调用后,并不是马上就释放对象锁的,
而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM才会在wait()对象锁的线程中随机选取一线程,
赋予其对象锁,唤醒线程,继续执行。
7.以下是我写的线程的一些例子,相信应该能够看懂,我就不多说了,有不理解的可以相互交流,共同进步。
生产者消费者的例子:
package com.wj.demo;
/*
class Info{
private String name="李新华";
private String content="java讲师";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
class Producer implements Runnable{
private Info info=null;
public Producer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean flag=false;
for(int i=0;i<50;i++){
if(flag){
this.info.setName("李兴华");
try {
Thread.sleep(90);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.setContent("java讲师");
flag=false;
}else{
this.info.setName("baidu");
try {
Thread.sleep(90);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.setContent("www.baidu.com");
flag=true;
}
}
}
}
class Consumer implements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.info.getName()+"--->"
+this.info.getContent());
}
}
}
*/
/*
class Info{
private String name="李新华";
private String content="java讲师";
public synchronized void set(String name,String content){
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.setContent(content);
}
public synchronized void get(){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.getName()+"-->"
+this.getContent());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
class Producer implements Runnable{
private Info info=null;
public Producer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean flag=false;
for(int i=0;i<50;i++){
if(flag){
this.info.set("李兴华","java讲师");
flag=false;
}else{
this.info.set("mldn", "www.mldn.com");
flag=true;
}
}
}
}
class Consumer implements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.get();
}
}
}
*/
/*
class Info{
private String name="李新华";
private String content="java讲师";
private boolean flag=false;
public synchronized void set(String name,String content){
if(!flag){
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.setContent(content);
flag=false;
super.notify();
}
public synchronized void get(){
if(flag){
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.getName()+"-->"
+this.getContent());
flag=true;
super.notify();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
class Producer implements Runnable{
private Info info=null;
public Producer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean flag=false;
for(int i=0;i<50;i++){
if(flag){
this.info.set("李兴华","java讲师");
flag=false;
}else{
this.info.set("mldn", "www.mldn.com");
flag=true;
}
}
}
}
class Consumer implements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.get();
}
}
}
*/
class Info{
private String name="张三";
//private String content="java讲师";
private boolean flag=false;
public synchronized void set(String name){
if(!flag){
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.setName(name);
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//this.setContent(content);
flag=false;
super.notify();
}
public synchronized void get(){
if(flag){
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.getName()+"-->"
);
flag=true;
super.notify();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/*public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}*/
}
class Producer implements Runnable{
private Info info=null;
public Producer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
boolean flag=false;
for(int i=0;i<20;i++){
if(flag){
this.info.set("张三");
flag=false;
}else{
this.info.set("李四");
flag=true;
}
}
}
}
class Consumer implements Runnable{
private Info info=null;
public Consumer(Info info){
this.info=info;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<20;i++){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.info.get();
}
}
}
public class ThreadDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Info i=new Info();
Producer pro=new Producer(i);
Consumer con=new Consumer(i);
new Thread(pro).start();
new Thread(con).start();
}
}
下面是程序的输出结果:
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
张三-->
李四-->
从运行结果可以看到的是,生产者生产一个,消费者消费一个,进行同步输出
下面是我的写的一个买票的线程例子:
package com.wj.demo;
class MyThread1 extends Thread{
private String name;
public MyThread1(String name){
this.name=name;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
System.out.println(name+i);
}
}
}
class MyThread2 implements Runnable{
private String name;
public MyThread2(String name){
this.name=name;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
System.out.println(name+i);
}
}
}
class MyThread3 implements Runnable{
private int ticket=5;
@Override
public void run() {
// TODO Auto-generated method stub
if(ticket>0){
System.out.println("卖票:ticket="+ticket--);
}
}
}
class MyThread4 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<3;i++){
System.out.println(Thread.currentThread().getName()+"运行,i="+i);
}
}
}
class MyThread5 implements Runnable{
private String name;
private int time;
public MyThread5(String name,int time){
this.name=name;
this.time=time;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(this.time);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(this.name+"线程,休眠"+this.time+"毫秒");
}
}
class MyThread6 implements Runnable{
private int ticket=110;
/*private String name=null;
public MyThread6(String name){
this.name=name;
}*/
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<200;i++){
synchronized(this){
if(ticket>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"卖票:ticket="+ticket--);
}
}
}
}
}
public class ThreadDemo1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//MyThread1 mt1=new MyThread1("线程A");
//MyThread1 mt2=new MyThread1("线程B");
//mt1.start();
//mt2.start();
/*
MyThread2 my1=new MyThread2("线程--A");
MyThread2 my2=new MyThread2("线程--B");
Thread th1=new Thread(my1);
Thread th2=new Thread(my2);
th1.start();
th2.start();*/
/*
MyThread3 my=new MyThread3();
new Thread(my).start();
new Thread(my).start();
new Thread(my).start();
new Thread(my).start();
new Thread(my).start();*/
/*
MyThread4 my=new MyThread4();
new Thread(my).start();
new Thread(my,"线程A").start();
new Thread(my,"线程B").start();
new Thread(my).start();
new Thread(my).start();*/
/*
MyThread5 my1=new MyThread5("线程A",10000);
MyThread5 my2=new MyThread5("线程B",20000);
MyThread5 my3=new MyThread5("线程C",30000);
MyThread5 my4=new MyThread5("线程D",40000);
new Thread(my1).start();
new Thread(my2).start();
new Thread(my3).start();
new Thread(my4).start();*/
MyThread6 mt=new MyThread6();
Thread t1=new Thread(mt,"A");
Thread t2=new Thread(mt,"B");
Thread t3=new Thread(mt,"C");
Thread t4=new Thread(mt,"D");
Thread t5=new Thread(mt,"E");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
程序的运行结果可能如下所示:
B卖票:ticket=110
B卖票:ticket=109
B卖票:ticket=108
B卖票:ticket=107
B卖票:ticket=106
B卖票:ticket=105
B卖票:ticket=104
B卖票:ticket=103
B卖票:ticket=102
B卖票:ticket=101
B卖票:ticket=100
B卖票:ticket=99
E卖票:ticket=98
E卖票:ticket=97
E卖票:ticket=96
E卖票:ticket=95
E卖票:ticket=94
E卖票:ticket=93
E卖票:ticket=92
E卖票:ticket=91
E卖票:ticket=90
E卖票:ticket=89
E卖票:ticket=88
E卖票:ticket=87
E卖票:ticket=86
E卖票:ticket=85
E卖票:ticket=84
E卖票:ticket=83
E卖票:ticket=82
E卖票:ticket=81
E卖票:ticket=80
E卖票:ticket=79
E卖票:ticket=78
E卖票:ticket=77
E卖票:ticket=76
D卖票:ticket=75
D卖票:ticket=74
D卖票:ticket=73
D卖票:ticket=72
C卖票:ticket=71
C卖票:ticket=70
C卖票:ticket=69
C卖票:ticket=68
C卖票:ticket=67
C卖票:ticket=66
C卖票:ticket=65
A卖票:ticket=64
A卖票:ticket=63
A卖票:ticket=62
C卖票:ticket=61
C卖票:ticket=60
C卖票:ticket=59
C卖票:ticket=58
C卖票:ticket=57
C卖票:ticket=56
C卖票:ticket=55
C卖票:ticket=54
C卖票:ticket=53
C卖票:ticket=52
C卖票:ticket=51
C卖票:ticket=50
D卖票:ticket=49
D卖票:ticket=48
D卖票:ticket=47
D卖票:ticket=46
D卖票:ticket=45
D卖票:ticket=44
D卖票:ticket=43
D卖票:ticket=42
D卖票:ticket=41
E卖票:ticket=40
E卖票:ticket=39
E卖票:ticket=38
E卖票:ticket=37
E卖票:ticket=36
E卖票:ticket=35
E卖票:ticket=34
E卖票:ticket=33
E卖票:ticket=32
E卖票:ticket=31
E卖票:ticket=30
E卖票:ticket=29
B卖票:ticket=28
B卖票:ticket=27
B卖票:ticket=26
B卖票:ticket=25
B卖票:ticket=24
B卖票:ticket=23
B卖票:ticket=22
B卖票:ticket=21
B卖票:ticket=20
B卖票:ticket=19
B卖票:ticket=18
B卖票:ticket=17
B卖票:ticket=16
B卖票:ticket=15
B卖票:ticket=14
E卖票:ticket=13
E卖票:ticket=12
D卖票:ticket=11
D卖票:ticket=10
D卖票:ticket=9
D卖票:ticket=8
D卖票:ticket=7
D卖票:ticket=6
D卖票:ticket=5
C卖票:ticket=4
C卖票:ticket=3
C卖票:ticket=2
C卖票:ticket=1
下面的程序展示的是,打印10次A,10次B,10次C,打印的顺序是ABCABCABC.......下面是用线程实现的代码。
代码里面的注释已经很清楚了,我就不再解释了,有问题的,欢迎一起交流,一起进步。
package com.wj.demo;
/*
* 1.Product类是一个产品类,用来表示生产产品
* 2.里面的有set和get方法,set方法用来设置生产什么样的产品,get是得到产品*/
class Product{
private String name="A";//产品的名字
private boolean flag=true;//标志,true代表可以生产,false代表可以取得产品
//注意:super.wait(),super.notifyAll()这2个方法,一定要是在synchronized所
//包含的代码块里面调用,也就是说只有拥有对象锁的线程,才能有权调用super.wait(),super.notifyAll()
//方法,否则会出错。之所以会这样,是因为super.wait()方法是把拥有该对象锁的线程放到等待该对象锁的队列中进行休息
//这个过程需要找到拥有对象锁的线程,所以super.wait()方法应该在synchronized里面的代码块中调用;
//同理,super.notifyAll()是用来唤醒在等待该对象锁队列中所有的线程,所以也需要和对象锁有关系,唤醒的是想得到
//该对象锁的所有线程,因此也需要在synchronized代码块中使用。
//synchronized表示只有拥有该对象锁的线程才能进入synchronized代码块,里面。
//综上所述,synchronized,super.wait(),super.notifyAll(),在进行同步控制的时候一般是需要一起配对使用
public synchronized void getName() {//得到产品的函数
if(flag){//如果标志为true,则代表只可以生产,不能进行取产品
try {
super.wait();//调用Object父类的方法,使得到该对象锁的线程等待,把该线程放到等待该对象锁的队列里面
//,并且释放cpu,和释放该对象的对象锁,使其他的线程可以得到该对象的锁
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(name);//打印产品的名字
try {
Thread.sleep(200);//该线程休眠200毫秒,释放cup,让其他的线程执行,但是不会释放对象锁
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
flag=true;//把标志置位true,表示已经取了产品了,可以进行生产了,已经不没有产品了,不能得到产品了
//调用了super.notifyAll()方法后,并不会马上执行,要等待synchronized代码块所有的程序执行完了以后才会
//释放对象锁,进行唤醒其他的线程
super.notifyAll();//调用父类Object的方法,释放对象锁,唤醒在等待该对象锁的所有线程
}
public synchronized void setName(String name) {
if(!flag){//如果flag为false则表示,只可以取产品,不能进行生产产品
try {
super.wait();//进行等待,和上面的一样
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(200);//解释如上
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.name = name;//设置产品的名字
flag=false;//设置标志,表示可以取产品了,不能再进行生产了
super.notifyAll();//如上所示,唤醒其他的想得到该对象锁的所有线程
}
}
//Factory类是一个工厂,用来控制生产什么样的产品
class Factory implements Runnable{
private Product product;//共享的对象
public Factory(Product product) {//构造函数,对product进行初始化
super();
this.product = product;
}
@Override
public void run() {//覆写的run方法,进行线程操作
// TODO Auto-generated method stub
for(int i=1;i<31;i++){
if(i%3==1){//如果余数为1,则生产A产品
product.setName("A");//生产A产品
}else if(i%3==2){//如果余数为2,则生产B产品
product.setName("B");//生产B产品
}else{//其他的生产C产品
product.setName("C");//生产C产品
}
}
}
}
//Customer是消费者类,用来使用工厂生产的产品
class Customer implements Runnable{
private Product product;//贡献资源对象
public Customer(Product product) {//构造函数,初始化product
super();
this.product = product;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=1;i<31;i++){
try {
Thread.sleep(500);//进行线程休眠,使打印有时间延迟
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(""+i+"----->");
this.product.getName();//消费产品
}
}
}
public class ThreadDemo4 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Product p=new Product();//创建共享资源对象
Factory fp=new Factory(p);//创建工厂
Customer cp=new Customer(p);//创建消费者
Thread tfp=new Thread(fp);//创建工厂线程进行生产
Thread tcp=new Thread(cp);//创建消费者线程进行消费
tfp.start();//启动线程
tcp.start();//启动线程
}
}
程序的运行结果如下:
1----->A
2----->B
3----->C
4----->A
5----->B
6----->C
7----->A
8----->B
9----->C
10----->A
11----->B
12----->C
13----->A
14----->B
15----->C
16----->A
17----->B
18----->C
19----->A
20----->B
21----->C
22----->A
23----->B
24----->C
25----->A
26----->B
27----->C
28----->A
29----->B
30----->C
到此线程的知识也就基本讲完了,发现对上面的知识进行总结以后,线程也就并没有那么难了,难得就是难于理解什么是多线程,多线程的运行过程。要是理解了多线程的运行过程,那么java中的线程也就没那么可怕了。最后一点就是要举义反三,融汇贯通,利用典型的生产者消费者模式,可以演变后解决很多线程的问题。希望好好理解生产者消费者模式。如果对线程还有什么问题,希望我们可以一起交流。
相关文章推荐
- Java线程(八):锁对象Lock-同步问题更完美的处理方式
- java基础问题---java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用
- Java线程(七):锁对象Lock-同步问题更完美的处理方式 .
- Java线程(七):锁对象Lock-同步问题更完美的处理方式
- java同步和互斥 : 线程之间通信
- Java线程同步问题之警察抓小偷
- java#3 java线程的同步问题
- java线程同步和互斥
- java线程中同步线程分组问题
- java线程同步问题
- java线程同步之死锁问题
- Java线程(七):锁对象Lock-同步问题更完美的处理方式
- Java线程基本用法与同步问题
- Java笔记3 多线程<1>线程概述、多线程的创建、多线程的安全问题、静态同步函数的锁、死锁
- java Thread:线程同步之互斥(2)
- 线程的同步问题(java)
- java线程同步问题的总结
- 如何解决Java线程同步中的阻塞问题
- java中的线程机制和线程的同步与互斥.
- Java并发编程之同步互斥问题