-----------------线程安全问题------------------

 1:进程和线程的概念:

  进程是一个实体,进程是执行中的程序,程序是一个没有生命的实体,只有处理器赋予程序生命时,他才能成为一个活动的实体,我们称之为进程
在一个进程内部,要同时干多件事情,就需要同时运行多个子任务,我们把进程内的这些子任务叫做线程
一个简单的比喻,多线程就像是火车上的每节车厢,而进程就是火车
2:线程的特点:

* 并发性
* 随机性
* 通道性
* c:在java中只有Thread类代表线程
* d:在java中使用线程的方式(在java中常见的创建线程的方式)
* 继承Thread类
* 实现Runnable接口
* 实现Callable接口
* 使用线程池
* 使用中间件
*
* d1:继承Thread类
* 编写自定义类继承Thread类
* 创建自定义类的对象
* 把使用线程完成的业务代码编写到run方法中
* 调用Thread类的start方法 启动线程
*
* d2:实现Runnable接口------》》如果线程服务的业务没有返回值 请使用 Runnable接口
* 为什么要使用实现实现Runnable接口的方式创建线程?
* 如果自定义的类已经有了父类 则不能使用d1的方式创建线程
* 使用Runnable接口实际上是把线程和要处理的业务功能解耦合(当需要线程给业务服务时 直接调用Thread(Runnable target))
*
* Runnable接口中只有一个方法需要我们实现 就是run方法 需要把要使用线程服务的业务代码放入run方法
*
* d3:实现Callable接口--------》》如果线程服务的业务需要返回值 请使用 Callable接口
* Callable接口中只有一个方法需要我们实现 就是call方法 需要把要使用线程服务的业务代码放入call方法
*
* 使用Runnable接口和使用Callable接口完成多线程编程的区别时什么?
* Runnable接口的run方法没有返回值 Callable接口的call方法是有一个泛型的返回值
* 以上的区别说明了如果线程服务的业务需要有返回值 请使用 Callable接口 否则直接使用Runnable接口
* 2个接口的实现类和线程对接的方式不一样
* Runnable接口是直接做Thread构造方法的参数
* Callable接口是由线程池去调用的
*
* d4:使用线程池
* 线程池 池化的概念
* 线程池就是把线程池化 提升系统的执行效率
* Executors ExecutorService 使用线程池常用的类
* 常用的线程池类型:
* newCachedThreadPool() 内存/缓存线程池
* newFixedThreadPool(int nThreads) 固定线程池
* newSingleThreadExecutor() 单一线程池
*
* ExecutorService es = Executors.newSingleThreadExecutor();
* es.submit(new Callable(){
* public int call(){
* ...... 业务代码
* }
* });
*
* 到线程池这里 通常使用线程都是只关注业务方法 把业务代码编写入Runnable接口的run 或者 Callable接口的call方法
* 然后直接提交给线程池执行即可
*
* java中的线程池是如何实现的?
* java中线程池的底层都是ThreadPoolExecutor实现的
*
* newCachedThreadPool-new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());

newFixedThreadPool-new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());

newSingleThreadExecutor-new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>())
所有的常用线程池底层都是ThreadPoolExecutor对象 只是每个参数对象不同而已

e:线程状态
创建 就绪 运行 阻塞 死亡

f:多线程的安全性问题 ******
f1:什么是线程的安全性问题?
发生多线程安全行问题的前提:
具有多线程环境
多个线程要有共享资源
每个线程处理共享资源的步骤都不是原子性的
以上3个前提同时满足 在某个时刻这个程序一定会发生安全性问题

f2:如何解决线程安全性问题
使用synchronized方式处理安全性问题
同步、异步
ThreadLocal 本地线程
volatile 改变了线程的内存执行方式

g:线程间通信
wait notify notifyall
lock

h:concurrent 并发包
这个包下边都是已经准备好的线程安全的类型或者集合
对于非线程安全的类型可以使用包下的原子类型
eg:
AtomicBoolean 线程安全的布尔型
AtomicInteger 线程安全的整型
......

线程安全的集合:
CopyOnWriteArrayList list
CopyOnWriteArraySet set
ConcurrentHashMap map
LinkedBlockingQueue queue
*

代码说明:

//创建一个单线程池 启动send方法
ExecutorService es = Executors.newSingleThreadExecutor();
es.submit(new Runnable() {

@Override
public void run() {
//保证调用send方法
send();

}
});

 










posted @ 2019-06-05 20:12  wuyingying  阅读(112)  评论(0编辑  收藏  举报