Java5 多线程

Java5之多线程方式

1:三个新加的多线程包

   Java 5.0里新加入了三个多线程包:java.util.concurrent, java.util.concurrent.atomic, java.util.concurrent.locks.

  • java.util.concurrent包含了常用的多线程工具,是新的多线程工具的主体。
  • java.util.concurrent.atomic包含了不用加锁情况下就能改变值的原子变量,比如说AtomicInteger提供了addAndGet()方法。Add和Get是两个不同的操作,为了保证别的线程不干扰,以往的做法是先锁定共享的变量,然后在锁定的范围内进行两步操作。但用AtomicInteger.addAndGet()就不用担心锁定的事了,其内部实现保证了这两步操作是在原子量级发生的,不会被别的线程干扰。
  • java.util.concurrent.locks包包含锁定的工具。

2:Callable 和 Future接口

   Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。Callable和Runnable有几点不同:

  • Callable规定的方法是call(),而Runnable规定的方法是run().
  • Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
  • call()方法可抛出异常,而run()方法是不能抛出异常的。
  • 运行Callable任务可拿到一个Future对象,通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。

3:Executor, ExecutorService和ScheduledExecutorService

4:Lockers和Condition接口

   在多线程编程里面一个重要的概念是锁定,假如一个资源是多个线程共享的,为了保证数据的完整性,在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作,从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized要害字来实现的,这样做存在几个问题:

  • 每次只能对一个对象进行锁定。若需要锁定多个对象,编程就比较麻烦,一不小心就会出现死锁现象。
  • 假如线程因拿不到锁定而进入等待状况,是没有办法将其打断

工作需求的多线程时序控制(子线程等待主线程执行完某一个方法之后在执行

       在JAVA中,是没有类似于PV操作、进程互斥等相关的方法的。JAVA的进程同步是通过synchronized()来实现的,需要说明的是,JAVA的synchronized()方法类似于操作系统概念中的互斥内存块,在JAVA中的Object类型中,都是带有一个内存锁的,在有线程获取该内存锁后,其它线程无法访问该内存,从而实现JAVA中简单的同步、互斥操作。明白这个原理,就能理解为什么synchronized(this)与synchronized(static XXX)的区别了,synchronized就是针对内存区块申请内存锁,this关键字代表类的一个对象,所以其内存锁是针对相同对象的互斥操作,而static成员属于类专有,其内存空间为该类所有成员共有,这就导致synchronized()对static成员加锁,相当于对类加锁,也就是在该类的所有成员间实现互斥,在同一时间只有一个线程可访问该类的实例。如果只是简单的想要实现在JAVA中的线程互斥,明白这些基本就已经够了。但如果需要在线程间相互唤醒的话就需要借助Object.wait(), Object.nofity()了。

    Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。


public class testThread {
	/**
	 * @param args
	 * 保证子线程等待主线程执行完某一个耗时方法之后在执行
	 */
	public static void main(String[] args) throws InterruptedException {
		
		    final testThread  test = new testThread();
		    System.out.println("Main Thread start..."+Thread.currentThread().getId());
            new Thread(new Runnable(){

				@Override
				public void run() {
					  synchronized(test){
					    try {
							test.wait();//等待主线程执行完某一个方法
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					  }
					System.out.println("Thread1 sleep run...."+Thread.currentThread().getId());
				}
            }).start();
            
            Thread.sleep(4000);//主线程挂起,释放CPU,Thread1 有机会执行了。
            System.out.println("Main Thread end..."+Thread.currentThread().getId());
            
            synchronized(test){
			    test.notify();
			}
	}
}


传统与新潮(Java5)两种方法解决一道笔试题目

建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。
http://blog.csdn.net/zyplus/article/details/6672775

package com.sort;

public class testThread2 {
	static class MyThread implements Runnable{
		String str ;
		public MyThread(String str){
			this.str = str;
		}
		@Override
		public void run() {
			  for(int i=0;i<10;i++){
				  System.out.println("thread ...."+Thread.currentThread().getId()+"  "+str);
			  }
		}
		
	}

	public static void main(String[] args) throws InterruptedException {
		  
		MyThread thread1 = new MyThread("A");
		MyThread thread2 = new MyThread("B");
		MyThread thread3 = new MyThread("c");
		
		new Thread(thread1).start();
		new Thread(thread2).start();
		new Thread(thread3).start();
	}
}



你可能感兴趣的:(Java5 多线程)