java 并发入门 by sdust iot zhl

来源:互联网 发布:golang 2.0 编辑:程序博客网 时间:2024/06/08 09:08

1.原因
关于并发
首先是为什么要用并发,在什么地方能用到并发
主要有以下两点,一个是速度,一个是设计可管理性
再多处理器上,使用并发可以利用这些额外的处理器,从而增加速度
而在单处理器上,将所有任务挨个执行看起来比运用多线程执行来的要快,因为节省了上下文切换的开销
但是如果单处理器只有一个线程遇到阻塞,会导致整个程序不能运行,而如果采用了并发,则可以避免这种情况

2.方法
实现并发,最简单直接的方法就是采取进程,进程会被操作系统相互隔离开,使之不会相互干涉,而JAVA使用的这种并发系统会共享内存和I/O这样的资源,因此多线程的难点在于如何调度这些资源,使之不会被多个任务同时访问

3.基本的线程机制
使用了线程机制,每个任务都将会由相应的执行线程来控制
一个线程就是一个进程当中的一个单一的顺序控制流,因此,单个进程可以处理多个并发的任务
主要底层机制就是切分CPU时间,将CPU的时间切分给所有的任务,每个人物都觉得自己一直在占用CPU

首先,定义任务
每个线程都会控制相应的任务
首先实现Runnable 接口 并且重写run方法

package ThreadTest; class Runnable_Test  implements Runnable {     static int  NumofThread=0;     final int ThreadId = NumofThread++;         public void run() {            for (int i =0;i<5;i++)                {                    System.out.println("这是第"+ThreadId+"个线程"+"的第"+i+"次循环");                }        }}

然后在写一个thread 类 的对象,接受一个上述的runnable 接口的对象,之后再调用这个thread类的 strat方法开启线程

public class ThreadTest {public static void main (String []args){    for (int j =0;j<5;j++)    {       new  Thread(new Runnable_Test()     ).start();    }}}

最后的输出结果如下:

这是第0个线程的第0次循环这是第1个线程的第0次循环这是第0个线程的第1次循环这是第0个线程的第2次循环这是第0个线程的第3次循环这是第0个线程的第4次循环这是第1个线程的第1次循环这是第1个线程的第2次循环这是第1个线程的第3次循环这是第1个线程的第4次循环这是第2个线程的第0次循环这是第3个线程的第0次循环这是第3个线程的第1次循环这是第3个线程的第2次循环这是第3个线程的第3次循环这是第3个线程的第4次循环这是第2个线程的第1次循环这是第2个线程的第2次循环这是第4个线程的第0次循环这是第4个线程的第1次循环这是第4个线程的第2次循环这是第4个线程的第3次循环这是第4个线程的第4次循环这是第2个线程的第3次循环这是第2个线程的第4次循环

由此可见,各个线程间的任务会有同时进行

控制同时进行的进程数
然而,JAVA语言本身以及计算机的CPU都不会运行每一个任务都分配一个进程,因为这样会产生大量同时进行的进程
这时就需要Excecutor 类对其进行限制
将之前代码的主类改成

public static void main (String []args){    ExecutorService ES  = Executors.newCachedThreadPool();    for (int j =0;j<5;j++)    {           ES.execute(new Runnable_Test());    }    ES.shutdown();}}

程序照常运行,且输出类似之前的

而修改executor的类型,将CachedThreadPool 改成 FixedThreadPool
就可以实现对任务实现,用有限的线程进行管理
这样,就不会每个线程都去创建新的线程,而新的任务会自动到线程池中找到相应的新线程,省去了创建线程的开销

也就是说cachedThreadPool是首选,当它出现问题时,再转去FixedThreadPool

从任务中产生返回值
Runnable 执行任务不返回值,希望任务返回一个值,就要采用callable接口
这个以后具体用到在进行分析

SLEEP setPriority yield join 方法的使用
Thread.sleep()

Thread.currentThread.setPriority()
优先级分为十级
1- 10 依次上升
但是这是JDK中的等级,在很多系统中不能映射的很好,比如WINDOWS系统中只有7种 ,因此建议只使用
MAX_PRIORITY NORM_PRIORITY MIN_PRIORITY

Yield方法用于表明该线程已经执行完毕,可以让步于其他线程,但是这并不代表他百分百被让步,因此不建议使用

Join 方法 ,假设一个线程为A ,一个线程 为B ,在线程A 的程序中加入 B.join()
那么A线程会被挂起,直到B线程执行完毕 ,而在B线程中加入interrupt()方法,可以中断B线程
4.后台(deamon)线程
另学

5.共享受限资源

package ThreadTest;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors; class Runnable_Test  implements Runnable {     static int  NumofThread=0;     final int ThreadId = NumofThread++;         public void run() {            for (int i =0;i<5;i++)                {                    System.out.println("这是第"+ThreadId+"个线程"+"的第"+i+"次循环");                }        }}public class ThreadTest {public static void main (String []args){    for (int j =0;j<5;j++)    {           new Thread(new Runnable_Test()).start();    }}}

这是一个普通的多线程示范,最后会出现多个线程同一时间段共同进行的情况
而加上synchronized 加上程序锁之后,就可以使相应的程序用一时间段只有一个线程在执行,从而防止资源的冲突。
如在run方法加上synchronized ,就可以是各个线程挨个执行

package ThreadTest;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors; class Runnable_Test  implements Runnable {     static int  NumofThread=0;     final int ThreadId = NumofThread++;         public synchronized void run() {            for (int i =0;i<5;i++)                {                    System.out.println("这是第"+ThreadId+"个线程"+"的第"+i+"次循环");                }        }}public class ThreadTest {public static void main (String []args){    for (int j =0;j<5;j++)    {           new Thread(new Runnable_Test()).start();    }}}
0 0
原创粉丝点击