`

java中的多线程

 
阅读更多

在java中有两种方式产生一个thread。 java.lang.Thread    java.lang.Runnable

1 某一个类实现Runnable接口,重点是重载run()方法;

2 某一类继承Thread类,并重载run()方法。

 

当某一个类是以上两种方法之一,当为该类new一个对象时,该对象并没有直接进入thread,直到执行 object.start()时,该对象才变成一个thread。并开始执行run()方法中的语句。

 

在多线程中,每个线程都有自己的数据空间,同时他们还可以访问进程的数据空间。多线程访问进程的数据空间的时候,需要考虑同步。

 

thread中常用的方法:

1 java.lang.Object.wait()  释放锁,(并且进入线程不可调度)并且直到有notify()或notifityAll()是才会继续往下执  行。(进入线程可调度)

2 java.lang.Object.notify() 释放锁,并且唤醒wait()的线程。

3 java.lang.Thread.sleep() 不释放锁,线程睡眠一段时间之后,继续执行。

java为每个对象分配一根锁。同时为类分配一个锁。当我们对类中的方法fun1使用synchronize,另一个方法fun2也是用synchronize,(假设线程1,2中执行的fun1,fun2属于同一个对象,(这样保证fun1,fun2使用的是同一个锁))当线程1执行fun1时,被线程2被调度,并且线程2执行fun2,那么此时线程2无法执行fun2,因为执行锁被fun1占用。

 

 

thread要考虑线程同步的问题,最典型的是生产与消费问题。有一个仓库,生产者生产的产品放入该仓库,消费者从该仓库中取出产品。仓库满之后,不允许在向其中放入,而仓库空时不允许从其中取出。 在这里。仓库是生产线程和消费线程的共享资源,这个共享资源被这2个线程改变。

 

 

 

 

public class App {

private Test test = new Test();

 class Add extends Thread {

public void run(){

while(true) {

try {

test.product();

} catch (Exception e) {

e.printStackTrace();

}

}

}

 }

class Sub extends Thread {

public void run(){

while(true){

try {

test.consume();

}catch (Exception e) {

e.printStackTrace();

}

}

}

}

 

public  Add getAdd(){

return new Add();

}

public  Sub getSub(){

return new Sub();

}

public static void main (String [] args){

App app = new App();

         App.Add addThread = app.getAdd();

         Sub subThread = app.getSub();

         subThread.start();

         addThread.start();    

}

}

 


当线程之间不采用同步时:test的类如下:




public class Test {
private static int containerMemory = 4;
private  int container ;

public   void product()throws Exception{
System.out.println(Thread.currentThread().getName()+ "  Product begin "+containerMemory);
if (containerMemory >= 10){
System.out.println("product wait");
//this.wait();
}else {
container = containerMemory ;
Thread.sleep(1000);
container ++ ;
containerMemory = container;
System.out.println(Thread.currentThread().getName()+ "  Product end "+containerMemory);
//this.notifyAll();
}
}
public    void consume() throws Exception {
System.out.println(Thread.currentThread().getName()+" consume begin  "+containerMemory);
if (containerMemory <= 0){
System.out.println("consume wait");
//this.wait();
}else {
container = containerMemory ;
container -- ;
containerMemory = container;
System.out.println(Thread.currentThread().getName()+" consume end "+containerMemory);
//this.notifyAll();
}
}

}


对应的打印为:
Thread-1 consume begin  4
Thread-1 consume end 3
Thread-0  Product begin 4
Thread-1 consume begin  3
Thread-1 consume end 2
Thread-1 consume begin  2
Thread-1 consume end 1
Thread-1 consume begin  1
Thread-1 consume end 0
Thread-1 consume begin  0
consume wait
Thread-0  Product end 4
Thread-0  Product begin 4
Thread-0  Product end 5
Thread-0  Product begin 5
Thread-0  Product end 6
Thread-0  Product begin 6
Thread-0  Product end 7
Thread-0  Product begin 7
Thread-0  Product end 8
Thread-0  Product begin 8
Thread-0  Product end 9
Thread-0  Product begin 9
Thread-0  Product end 10
Thread-0  Product begin 10
product wait

可以看到上面打印的蓝色部分出现了错误。product的过程被consume打断。product读取containerMemory之后,修改containerMemory,然后再把修改之写入containerMemory,但是在读containerMemory之后,写containerMemory之前被consume打断,而consume打断之后又修改了containerMemory的值。导致produce的containerMemory值过期。

 

 

 

现在给test加上同步:

 

 

 

 

public class Test {

private static int containerMemory = 4;

private  int container ;

 

public synchronized  void product()throws Exception{

System.out.println(Thread.currentThread().getName()+ "  Product begin "+containerMemory);

if (containerMemory >= 10){

System.out.println("product wait");

this.wait();

}else {

container = containerMemory ;

Thread.sleep(1000);

container ++ ;

containerMemory = container;

System.out.println(Thread.currentThread().getName()+ "  Product end "+containerMemory);

this.notifyAll();

}

}

public  synchronized  void consume() throws Exception {

System.out.println(Thread.currentThread().getName()+" consume begin  "+containerMemory);

if (containerMemory <= 0){

System.out.println("consume wait");

this.wait();

}else {

container = containerMemory ;

container -- ;

Thread.sleep(1000);

containerMemory = container;

System.out.println(Thread.currentThread().getName()+" consume end "+containerMemory);

this.notifyAll();

}

}

 

}


 

打印为:

 

 

 

Thread-1 consume begin  4

Thread-1 consume end 3

Thread-1 consume begin  3

Thread-1 consume end 2

Thread-1 consume begin  2

Thread-1 consume end 1

Thread-1 consume begin  1

Thread-1 consume end 0

Thread-1 consume begin  0

consume wait

Thread-0  Product begin 0

Thread-0  Product end 1

Thread-0  Product begin 1

Thread-0  Product end 2

Thread-0  Product begin 2

Thread-0  Product end 3

Thread-1 consume begin  3

Thread-1 consume end 2

Thread-1 consume begin  2

Thread-1 consume end 1

Thread-1 consume begin  1

Thread-1 consume end 0

Thread-1 consume begin  0

consume wait

Thread-0  Product begin 0

Thread-0  Product end 1

Thread-0  Product begin 1

Thread-0  Product end 2

Thread-0  Product begin 2

Thread-0  Product end 3

Thread-0  Product begin 3

Thread-0  Product end 4

Thread-0  Product begin 4

Thread-0  Product end 5

Thread-0  Product begin 5

Thread-0  Product end 6

Thread-0  Product begin 6

Thread-0  Product end 7

Thread-0  Product begin 7

Thread-0  Product end 8

Thread-1 consume begin  8

Thread-1 consume end 7

Thread-1 consume begin  7

Thread-1 consume end 6

Thread-1 consume begin  6

Thread-1 consume end 5

Thread-1 consume begin  5

Thread-1 consume end 4

Thread-1 consume begin  4

Thread-1 consume end 3

Thread-1 consume begin  3

Thread-1 consume end 2

Thread-1 consume begin  2

Thread-1 consume end 1

Thread-1 consume begin  1

Thread-1 consume end 0

Thread-1 consume begin  0

consume wait

Thread-0  Product begin 0

Thread-0  Product end 1

Thread-0  Product begin 1

Thread-0  Product end 2

Thread-0  Product begin 2

Thread-0  Product end 3

Thread-0  Product begin 3

Thread-0  Product end 4

Thread-1 consume begin  4

Thread-1 consume end 3

Thread-1 consume begin  3

Thread-1 consume end 2

Thread-1 consume begin  2

Thread-1 consume end 1

Thread-1 consume begin  1

Thread-1 consume end 0

Thread-1 consume begin  0

consume wait

Thread-0  Product begin 0

可以看出cosume的过程不会被product打断,同样product也不会被consume打断。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics