java 多线程 小结

前面有篇博文是小结c#的多线程的 http://www.cnblogs.com/sylvanas2012/archive/2012/07/26/2610591.html

java有点不同,实现多线程有两种方式:继承类Thread, 和 实现接口Runnable。

thread类有一个run函数,它是线程的入口,当启动一个新线程是,就从这个函数开始执行;

View Code
public class ThreadTest  extends Thread{

    public void run()
    {
        for (int i=0;i<5;i++)
        {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
    }
    
    public static void main(String[] args)
    {
        ThreadTest test1 = new ThreadTest();
        ThreadTest test2 = new ThreadTest();
        
        test1.start();
        test2.start();
    }
}

注意线程是调用start()来开始的。

Runnable有一点点不同,实现这个类的时候和Thread一样,但是创建线程的时候还是放入一个Thread中创建:

View Code
public class RunnableTest implements Runnable
{

    private int cnt;
    
    public RunnableTest(int n)
    {
        super();
        cnt = n;
    }
    
    public void run()
    {
        for (int i=0;i<5;i++)
        {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+" "+i+" "+--cnt);
        }
    }
    
    public static void main(String[] args)
    {
        RunnableTest t = new RunnableTest(10);
        Thread ta = new Thread(t);
        Thread tb = new Thread(t);
        
        ta.start();
        tb.start();
    }
}

 Thread和Runnable基本用法都是差不多的,但是从上面的例子可以看出,Runnable比较方便进程间数据的共享(公用了一个cnt计量单位),所以一样都使用Runnable。
线程常用的几个函数:

join():  强制等待线程执行完毕。 例如如果在主线程里面加一句ta.join(),那么主线程会一直等待ta执行返回才接着执行后面的代码。但是在join之前已经创建的其他线程,则不会受影响,继续执行。

interrupt(): 挺有意思的一个函数,如果线程在执行sleep()函数 ,则打断它(以让sleep()函数抛出一个异常的方式中断),执行后面的语句。

setDaemon(true):设置为守护进程。守护进程的优先级是最低的,如果一个程序只剩下守护进程,那么它就中断所有守护进程而退出。 最常见的情况是,如果创建的全部是守护进程,那么当主函数main执行完毕后,就立刻终止所有线程而退出。

synchronized同步符号用法: 保证同一时刻,某段代码只有一个线程在执行。

wait()和notify(),notifyAll():让线程等待/唤醒。这两个函数比较奇怪,目前我不是很熟练,要配合synchronized符号使用,请看下面这个生产者-消费者例子(网上直接贴来的,写的挺好的):

View Code
public class tt {

    public static void main(String[] args) {
        Storage s = new Storage();
        Producer p = new Producer(s);
        Consumer c = new Consumer(s);
        Thread tp = new Thread(p);
        Thread tc = new Thread(c);
        tp.start();
        tc.start();

    }
}

class Consumer implements Runnable {//消费者    
    Storage s = null;
    public Consumer(Storage s){
        this.s = s;
    }
    public void run() {
        for(int i=0; i<20; i++){
            Product p = s.pop();//取出产品
            try {
                Thread.sleep((int)(Math.random()*1500));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }

}

class Producer implements Runnable {//生产者
    Storage s = null;
    
    public Producer(Storage s){
        this.s = s;
    }

    public void run() {
        for(int i=0; i<20; i++){
            Product p = new Product(i);
            s.push(p);    //放入产品
//            System.out.println("生产者放入:" + p);
            try {
                Thread.sleep((int)(Math.random()*1500));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

class Product {
    int id;
    
    public Product(int id){
        this.id = id;
    }
    
    public String toString(){//重写toString方法
        return "产品:"+this.id;
    }
}

 
class Storage {
    int index = 0;
    Product[] products = new Product[5];
    
    public synchronized void push(Product p){//放入
        while(index==this.products.length){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.products[index] = p;
        System.out.println("生产者放入"+index+"位置:" + p);
        index++;
        this.notifyAll();
    }
    
    public synchronized Product pop(){//取出
        while(this.index==0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        index--;
        this.notifyAll();
        System.out.println("消费者从"+ index+ "位置取出:" + this.products[index]);
        return this.products[index];
    }
}

 大致流程:生产者每次产生一个产品,消费者一次消费一个产品; 仓库容量有限,当满存的时候,生产者就需要等待,直到有消费者消费,才被唤醒; 如果仓库是空的,那么消费者就不能消费,要等待,知道生产者生产出一个产品,并唤醒消费者。

 

posted on 2012-12-09 23:27  leavingseason  阅读(1071)  评论(0编辑  收藏  举报

导航

Bye!