并发编程可以帮助我们将程序划分为多个分离的、独立运行的任务。通过多线程机制,这些独立任务中的每一个都将由执行线程来驱动。一个线程就是在进程中的一个单一的顺序控制流,因此单个进程可以拥有多个并发执行的任务,但是程序使得每个任务都好像拥有自己的CPU一样,其底层机制是切分CPU时间。CPU会轮流为每个任务分配占用时间。
每个线程拥有各自独立的地址空间,而其中的静态成员变量是可以被多个线程共享的,例如下面程序中的i,i的地址是唯一的,并且永远存放在静态区域,因此,每次对i进行加载读取写入都是有可能发生不正当竞争的,为了保证读写安全,特别对i进行加锁synchronized,这样保证了安全读写。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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));
???????? }
???? }
???? ?} |
?
?
测试代码:
?
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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();
???? }
} |
?
?
测试结果:
?
?
1
2
3
4
5
6
7
8
9
10
|
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是个泛型接口,其中必须要实现的方法是Call()方法,该方法的返回值即该任务向主线程提交的返回值,由于是泛型的,因此我们可以返回任意类型的对象。
下面,我们来进行多个求和任务的分割,代码如下:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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;
???? }
?
} |
?
?
测试代码:
?
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
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" );
???? }
} |
?
?
为了与传统的单线程方法进行比较,为此也写了一个单线程的程序:
?
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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语句块。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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!" );
???????? }
???? }
} |
?
?
测试类:
?
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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 );
???? }
} |
?
?
测试结果:
?
?
1
2
3
4
5
6
7
8
9
10
|
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
|
?
?
通过下面的代码运行结果我们会发现,对于守护线程而言,它的所有子线程也都是守护线程。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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();
???????? }
???? }
?
} |
?
?
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package concurrency;
?
public class DaemonSpawn implements Runnable {
?
???? @Override
???? public void run() {
???????? while ( true ) {
???????????? //让步
???????????? Thread.yield();
???????? }
???? }
?
} |
?
?
测试代码:
?
?
1
2
3
4
5
6
7
8
9
10
11
12
|
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 );
???? }
} |
?
?
测试结果:
?
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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
|
最后欢迎大家扫码关注,我们一起学习,进步和交流!?
本公连接也是一个温馨的技术互动交流的小家园,有什么问题随时都可以留言,欢迎大家来访!?
?
原文:http://3264529882.iteye.com/blog/2236414