码迷,mamicode.com
首页 > 编程语言 > 详细

Java并发深度学习(一)

时间:2015-08-18 23:00:15      阅读:352      评论:0      收藏:0      [点我收藏+]

标签:

并发编程简介

并发编程可以帮助我们将程序划分为多个分离的、独立运行的任务。通过多线程机制,这些独立任务中的每一个都将由执行线程来驱动。一个线程就是在进程中的一个单一的顺序控制流,因此单个进程可以拥有多个并发执行的任务,但是程序使得每个任务都好像拥有自己的CPU一样,其底层机制是切分CPU时间。CPU会轮流为每个任务分配占用时间。

线程共享静态变量

每个线程拥有各自独立的地址空间,而其中的静态成员变量是可以被多个线程共享的,例如下面程序中的i,i的地址是唯一的,并且永远存放在静态区域,因此,每次对i进行加载读取写入都是有可能发生不正当竞争的,为了保证读写安全,特别对i进行加锁synchronized,这样保证了安全读写。


package concurrency;
/**
 * 并发问题,多线程的静态变量可以共享i
 * @author zzw922cn
 *
 */
public class CountRunnable implements Runnable {

	private static Integer i=0;
	@Override
	public void run() {
		synchronized(i) {
			System.out.println(Thread.currentThread().getName()+":"+(++i));
		}
	}
	
}



测试代码:



package concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test1 {

	public static void main(String[] args) {
		//Executors.newCachedThreadPool()用来新建线程池,如果有空闲线程就使用它,否则就新建新线程
		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		Thread[] thread = new Thread[10];
		for(int i=0;i<thread.length;i++) {
			thread[i]=new Thread(new CountRunnable());
			newCachedThreadPool.submit(thread[i]);
		}
		newCachedThreadPool.shutdown();
	}
}



测试结果:



pool-1-thread-2:2
pool-1-thread-4:4
pool-1-thread-3:3
pool-1-thread-1:1
pool-1-thread-5:5
pool-1-thread-6:6
pool-1-thread-7:7
pool-1-thread-8:8
pool-1-thread-10:9
pool-1-thread-9:10



从任务中返回值(Callable接口)

有时候,我们在分割任务时,同时还希望每个任务执行完毕能够返回一些数据给主进程,这时候我们可以使用实现Callable接口的方式来实现。Callable是个泛型接口,其中必须要实现的方法是Call()方法,该方法的返回值即该任务向主线程提交的返回值,由于是泛型的,因此我们可以返回任意类型的对象。

下面,我们来进行多个求和任务的分割,代码如下:


package concurrency;

import java.util.concurrent.Callable;

public class CountNumberTask implements Callable<Integer> {

	private int num;
	
	/**
	 * 构造函数
	 * @param num 末尾数
	 */
	public CountNumberTask(int num) {
		this.num = num;
	}

	/**
	 * 实现call函数,返回结果
	 */
	@Override
	public Integer call() throws Exception {
		int sum=0;
		for(int i=1;i<=num;i++) {
			sum+=i;
		}
		return sum;
	}

}



测试代码:



package concurrency;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
 * 耗时26秒
 * @author zzw922cn
 *
 */
public class CountNumberTest {

	public static void main(String[] args) {
		long t1 = System.currentTimeMillis();
		ExecutorService newCachedThreadPool = Executors.newFixedThreadPool(2);
		for(int i=1;i<=300000;i++) {
			Future<Integer> submit = newCachedThreadPool.submit(new CountNumberTask(i));
			try {
				Integer integer = submit.get();
				System.out.println(integer);
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		newCachedThreadPool.shutdown();
		long t2 = System.currentTimeMillis();
		System.out.println("多线程耗时"+(t2-t1)/1000.0+"s");
	}
}



为了与传统的单线程方法进行比较,为此也写了一个单线程的程序:



package concurrency;

/**
 * 耗时37秒
 * @author zzw922cn
 *
 */
public class CountNumberTest2 {

	public static void main(String[] args) {
		long t1 = System.currentTimeMillis();
		for(int i=1;i<=300000;i++) {
			int sum=0;
			for(int j=0;j<=i;j++) {
				sum+=j;
			}
			System.out.println(sum);
		}
		long t2 = System.currentTimeMillis();
		System.out.println("单线程耗时"+(t2-t1)/1000.0+"s");
	}
}



通过运行后,发现使用多线程耗时26s,单线程花了37s。


守护线程

所谓守护线程(又称作后台线程),是指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的一部分。当所有非守护进程结束时,程序就终止了,同时也会杀死程序的所有守护线程,守护线程在被杀死时,不会执行finally语句块。


package concurrency;

public class DeamonRunnable implements Runnable {

	@Override
	public void run() {
		try {
			while(true) {
				Thread.sleep(100);
				System.out.println(Thread.currentThread()+" "+this);
			}
		} catch(InterruptedException ex) {
			System.out.println("Sleep() interrupted!");
		}
	}
}



测试类:



package concurrency;

import java.util.concurrent.TimeUnit;

public class DeamonRunnableTest {

	public static void main(String[] args) throws InterruptedException {
		for(int i=0;i<10;i++) {
			Thread thread = new Thread(new DeamonRunnable());
			thread.setDaemon(true);
			thread.start();
		}
		//设置主线程休眠,所以能看到守护线程
		TimeUnit.MILLISECONDS.sleep(175);
	}
}



测试结果:



Thread[Thread-1,5,main] concurrency.DeamonRunnable@4908d73b
Thread[Thread-6,5,main] concurrency.DeamonRunnable@3f91c80b
Thread[Thread-5,5,main] concurrency.DeamonRunnable@1fb44aeb
Thread[Thread-0,5,main] concurrency.DeamonRunnable@12d4f26
Thread[Thread-2,5,main] concurrency.DeamonRunnable@210c4256
Thread[Thread-4,5,main] concurrency.DeamonRunnable@65c16078
Thread[Thread-3,5,main] concurrency.DeamonRunnable@7dca373f
Thread[Thread-9,5,main] concurrency.DeamonRunnable@7105d5e
Thread[Thread-8,5,main] concurrency.DeamonRunnable@7995373b
Thread[Thread-7,5,main] concurrency.DeamonRunnable@6bad1bc1



守护线程的子线程

通过下面的代码运行结果我们会发现,对于守护线程而言,它的所有子线程也都是守护线程。


package concurrency;

public class Daemon implements Runnable {

	private Thread[] t=new Thread[10];
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<t.length;i++) {
			t[i]=new Thread(new DaemonSpawn());
			t[i].start();
			System.out.println(t[i]+"has started!");
		}
		
		for(int i=0;i<t.length;i++) {
			System.out.println(t[i]+"is DaemonThread:"+t[i].isDaemon());
		}
		
		while(true) {
			Thread.yield();
		}
	}

}



package concurrency;

public class DaemonSpawn implements Runnable {

	@Override
	public void run() {
		while(true) {
			//让步
			Thread.yield();
		}
	}

}



测试代码:



package concurrency;

public class DaemonTest {

	public static void main(String[] args) throws InterruptedException {
		Thread thread = new Thread(new Daemon());
		thread.setDaemon(true);
		thread.start();
		System.out.println(thread+"isDaemonThread:"+thread.isDaemon());
		Thread.sleep(100);
	}
}



测试结果:



Thread[Thread-0,5,main]isDaemonThread:true
Thread[Thread-1,5,main]has started!
Thread[Thread-2,5,main]has started!
Thread[Thread-3,5,main]has started!
Thread[Thread-4,5,main]has started!
Thread[Thread-5,5,main]has started!
Thread[Thread-6,5,main]has started!
Thread[Thread-7,5,main]has started!
Thread[Thread-8,5,main]has started!
Thread[Thread-9,5,main]has started!
Thread[Thread-10,5,main]has started!
Thread[Thread-1,5,main]is DaemonThread:true
Thread[Thread-2,5,main]is DaemonThread:true
Thread[Thread-3,5,main]is DaemonThread:true
Thread[Thread-4,5,main]is DaemonThread:true
Thread[Thread-5,5,main]is DaemonThread:true
Thread[Thread-6,5,main]is DaemonThread:true
Thread[Thread-7,5,main]is DaemonThread:true
Thread[Thread-8,5,main]is DaemonThread:true
Thread[Thread-9,5,main]is DaemonThread:true
Thread[Thread-10,5,main]is DaemonThread:true






Java并发深度学习(一)

标签:

原文地址:http://my.oschina.net/zzw922cn/blog/494168

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!