CPU的运行,宏观上并行,微观上串行。

进程和线程之间的问题

一个进程是一个独立的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源。

多线程编程的好处是什么?

在多线程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲的状态。多个线程共享堆内存,因此创建多个线程去执行一些任务会比创建多个进程更好。例如在下载文件的时候,多个线程的下载是共享下载的资源的,所以多个线程的下载可以更快。

如何在java中运用多线程

对某一资源的共同使用和修改

对于资源的使用,有可能会出现同一时间内对对象的使用,造成错误的发生。例如下面的代码

public class Test02 {
	public static void main(String[] args) {
		Run1 run = new Run1();
		Thread th = new Thread(run);
		Thread th1 = new Thread(run);
		Thread th2 = new Thread(run);
		th.start();
		th1.start();
		th2.start();
	}

}

 class Run1 implements Runnable{
	 private  int i =100;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(i>0){
			System.out.println(Thread.currentThread().getName()+"   "+i);
			i--;
		}
		
	}
	
}

class Run1 继承了 Runnable,并且通过通过多个线程共享一个类的地址使用,造成了有可能同一时间对同一个对象的重复调用。资源会有可能出现错误。

在这个时候需要在某段代码中使用锁,来确保这段代码只能某个线程去访问。synchronized()这个很好的复合的代码的保护。

public class Test02 {
	public static void main(String[] args) {
		Run1 run = new Run1();
		
		Thread th = new Thread(run);
		Thread th1 = new Thread(run);
		Thread th2 = new Thread(run);
		
		th.start();
		th1.start();
		th2.start();
	}

}

 class Run1 implements Runnable{
	 private  int i =10000;
	 private Object one=new Object();
	 private Boolean changed = true;
	@Override
	public  void run() {
		// TODO Auto-generated method stub
		while(changed){
			
			if(i!=1){
				
			synchronized (one) {
				 System.out.println(Thread.currentThread().getName()+"   "+i--);
			}
			}else changed=false;
		}
	}
	
}

在上面的代码中有什么区别呢?首先多了个synchronized(),和Object对象,Object是任何的父类。synchronized()中需要绑定随意一个类来进行对象代码锁的操作。

在JDK1.5以后多了个Clone接口,这个是可以进行锁的操作。 使用方法 Lock lock = new ReetrantLock(); Condition con = lock.newConition(); Condition是可以从用一个Lock中多个定义。 方法con.await() con.signal();

class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)
         notFull.await();
       items[putptr] = x;
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr];
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
 }

在进行某些操作的时候,因为对数据操作先后顺序交互的需求,所以可以让某一先开始的线程等待后面进来的线程先完成,然后才唤醒该线程。这涉及线程的通信问题。

互斥,同步,死锁