`
singo107
  • 浏览: 29447 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java多线程基础(详解)

阅读更多

创建、启动线程有两种方式

 

1、继承Thread基类

public class AThread extends Thread {    
    public void run() {...}
}
new AThread().start();

2、实现Runnable接口

public class AClass implements Runnable {
	public void run() {...}
}
AClass aClass = new AClass();
new Thread(aClass).start();

 

sleep、join、yield、wait、notify、notifyAll、synchronized

 

sleep()是Thread的静态方法;

join()、yield()是Thread的实例方法;

wait()、notify()、notifyAll()是Object的实例方法,即任何一个类都有这3个方法;

synchronized为对象同步锁

 

sleep(long millis)在指定的时间段内挂起当前线程,此间不会被系统调度并执行,而其他线程可以抢夺CPU时间片,但如果该方法在同步方法(或同步代码区域)中调用,此间将不会释放锁,

sleep(long millis, int nanos),第二个参数表示精确到纳秒;

 

yield(),和sleep一样,只是让出当前线程,不会挂起一段时间

 

join(),是Thread的实例方法,主线程调用子线程的join()方法,主线程将阻塞,直到子线程运行结束,主线程才能重新启动,代码如下:

public class AThread extends Thread {

	public AThread(String name) {
		super(name);
	}

	@Override
	public void run() {
		for (int i = 0; i < 3; i++) {
			System.out.println("[" + super.getName() + "]:i=" + i);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class MainThread {

	public static void main(String[] args) {
		System.out.println("main thread start.");
		AThread aThread = new AThread("aThread");
		aThread.start();
		try {
			aThread.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("main thread end.");
	}
}

运行结果:

main thread start.

[aThread]:i=0

[aThread]:i=1

[aThread]:i=2

main thread end.

另外,对于join方法,只会阻塞调用子线程的上级线程,对于调用上级线程的上上级线程是没有阻塞作用的。

join(long millis)、join(long millis, int nanos) 表示阻塞上级线程的时间,如果超过指定时间,上级线程将不再阻塞。

 

wait()、notify()、nofityAll(),这3个方法是Object类的实例方法

在多线程处理中,会遇到这样的业务问题,如产品消费完之后必须等待生产者生产以后才能重新消费,以生产者、消费者问题为例,说说wait和notify的用法,代码下面有(请参看Factory类)。

 

 

1、调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {...} 代码段内。

2、调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {...} 代码段内唤醒A。

3、当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。

4、如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。

5、obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。

6、当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。

 

另外,wait(long timeout)、wait(long timeout, int nanos)表示等待的最大时长。

 

以下是“生产者、消费者问题”的java源码

 

1、Product,表示产品实体

public class Product {

	private int id;

	public Product(int id) {
		this.id = id;
	}

	public int getId() {
		return id;
	}
}

2、Producer,生产者

public class Producer implements Runnable {

	private Factory factory;

	public Producer(Factory factory) {
		this.factory = factory;
	}

	@Override
	public void run() {
		Product product = null;
		for (int i = 0; i < 100; i++) {
			product = new Product(i);
			factory.push(product);
			System.out.println("+push product[" + product.getId() + "].");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

3、Consumer,消费者

public class Consumer implements Runnable {

	private Factory factory;

	public Consumer(Factory factory) {
		this.factory = factory;
	}

	@Override
	public void run() {
		while (true) {
			Product product = factory.pop();
			System.out.println("-pop product[" + product.getId() + "].");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

4、Factory,工厂

public class Factory {

	private int index;
	private Product[] productArray = new Product[100];

	public synchronized void push(Product product) {
		while (index == productArray.length) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		productArray[index] = product;
		index++;
	}

	public synchronized Product pop() {
		while (index == 0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notifyAll();
		index--;
		return productArray[index];
	}
}

5、Control,主控程序

public class Control {

	public static void main(String[] args) {

		Factory factory = new Factory();

		Producer producer = new Producer(factory);
		Thread producerThread = new Thread(producer);
		producerThread.start();

		Consumer consumer1 = new Consumer(factory);
		Thread consumerThread1 = new Thread(consumer1);
		consumerThread1.start();
	}
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics