java有点不同,实现多线程有两种方式:继承类Thread, 和 实现接口Runnable。
thread类有一个run函数,它是线程的入口,当启动一个新线程是,就从这个函数开始执行;
View Code
public class ThreadTest extendsThread{public voidrun()
{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 voidmain(String[] args)
{
ThreadTest test1= newThreadTest();
ThreadTest test2= newThreadTest();
test1.start();
test2.start();
}
}
注意线程是调用start()来开始的。
Runnable有一点点不同,实现这个类的时候和Thread一样,但是创建线程的时候还是放入一个Thread中创建:
View Code
public class RunnableTest implementsRunnable
{private intcnt;public RunnableTest(intn)
{super();
cnt=n;
}public voidrun()
{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 voidmain(String[] args)
{
RunnableTest t= new RunnableTest(10);
Thread ta= newThread(t);
Thread tb= newThread(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 classtt {public static voidmain(String[] args) {
Storage s= newStorage();
Producer p= newProducer(s);
Consumer c= newConsumer(s);
Thread tp= newThread(p);
Thread tc= newThread(c);
tp.start();
tc.start();
}
}class Consumer implements Runnable {//消费者
Storage s = null;publicConsumer(Storage s){this.s =s;
}public voidrun() {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;publicProducer(Storage s){this.s =s;
}public voidrun() {for(int i=0; i<20; i++){
Product p= newProduct(i);
s.push(p);//放入产品//System.out.println("生产者放入:" + p);
try{
Thread.sleep((int)(Math.random()*1500));
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}classProduct {intid;public Product(intid){this.id =id;
}public String toString(){//重写toString方法
return "产品:"+this.id;
}
}classStorage {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];
}
}
大致流程:生产者每次产生一个产品,消费者一次消费一个产品; 仓库容量有限,当满存的时候,生产者就需要等待,直到有消费者消费,才被唤醒; 如果仓库是空的,那么消费者就不能消费,要等待,知道生产者生产出一个产品,并唤醒消费者。