最近在看并发,看到两篇blog,总结的很好,转过来学习下,以后如果有啥想法的,再在这两篇博客的基础之上做些补充和完善。。。
最近复习Java并发,写点东西总结总结。好记性不如烂博客。
并发
什么是并发?
与顺序编程不同,并发使得程序在同一时刻可以执行多个操作(宏观)。
为什么需要并发?
通常是为了提高程序的运行速度或者改善程序的设计。
线程
Java对并发编程提供了语言级别的支持。Java通过线程来实现并发编程。一个线程通常完成某个特定的任务,一个进程可以拥有多个线程,当这些线程一起执行的时候,就实现了并发。与操作系统中的进程相似,每个线程看起来好像拥有自己的CPU,但是其底层是通过切分CPU时间来实现的。与进程不同的是,线程并不是相互独立的,它们通常要相互合作来完成一些任务。
实现线程
你可以通过继承Thread类来实现自己的线程,关键的部分是,依靠重写run()方法来完成线程的工作。先写一个简单的线程,它的任务就是在控制台中依次打印出0,1,2,3,4。
之后,我们启动两个这样的线程,让它们分别完成自己的任务。
执行结果如下:
0 0 1 1 2 2 3 3 4 4
结果似乎并不是像单线程程序那样,分先后两次分别打印出0,1,2,3,4,而是两个线程似乎同时在执行一样,都分别打印出自己的0,1,2,3,4,这便是“并行”。在调用一个Thread对象的start()方法之后,JVM就会启动一个新的线程。
直接继承Thread类并不是一个好的方法。因为有时候我们自己的线程类可能需要继承别的类,而Java并不支持多重继承。这个时候Runnable接口就有了用处(实际上Thread类本身也实现了Runnable接口)。我们要做的就是实现Runnable接口,并且重写run()方法。最后将一个实现了Runnable接口的类的实例交给Thread类的构造函数,就可以实例化出一个可用的线程了。
实际上,在很多时候,我们可以将一个线程看做一个任务,这个线程存在的价值就是为了完成某个任务。
休眠
正如第一个例子那样,我们可以让一个线程暂时休息一会儿。Thread类有一个sleep静态方法,你可以将一个long类型的数据当做参数传进去,单位是毫秒,表示线程将会休眠的时间。第一个例子中之所以调用了sleep方法,是因为打印5个数字的时间太短,如果不休眠的话可能看不到“并发”的效果,因为CPU的时间片还来不及转换,线程的任务就已经完成了。
让步
Thread类还有一个名为yield()的静态方法。这个方法的作用是为了建议当前正在运行的线程做个让步,让出CPU时间给别的线程来运行。程序中可能会有一个线程在某个时刻已经完成了一大部分的任务,并且这个时候让别的线程来运行比较合理。这样的情况下,就可以调用yield()方法进行让步。不过,调用这个方法并不能保证一定会起作用,毕竟它只是建议性的。所以,不应该用这个方法来控制程序的执行流程。
串入(join)
当一个线程t1在另一个线程t2上调用t1.join()方法的时候,线程t2将等待线程t1运行结束之后再开始运行。正如下面这个例子:
输出结果为:
10
11
12
13
14
0
1
2
3
4
优先级
我们可以给一个线程设定一个优先级。线程调度器在做调度工作的时候,优先级越高的线程越可能得到先运行的机会。Thread类的setPriority方法和getPriority方法分别用来设置线程的优先级和获取线程的优先级。由于线程调度器根据优先级的大小来调度线程的效果在各种不同的JVM上差别很大,所以在绝大多数情况下,我们不应该依靠设定优先级来完成我们的工作,保持默认的优先级是一条很好的建议。
守护线程(deamon thread)
通常,程序中有一些线程的工作并不是不可或缺的,它只是用来协助其他线程来工作。这样的线程叫做守护线程或者后台线程。当进程中的所有非守护线程结束时,守护线程也就终止了,就算它还没有完全完成自己的任务。我们可以在一个线程启动之前调用setDaemon()方法来将这个线程设定成守护线程。
转自: http://blog.psjay.com/posts/summary-of-java-concurrency-one-thread-fundation/