线程、多线程、线程池
2016-05-24 10:29
141 查看
·
线程
线程是操作系统能够进行运算调度的最小单位,线程被包含在进程中,一个进程至少包含一个线程,进程也可以并发的执行多个线程。
线程的生命周期:
新建状态(New) 新创建了一个线程,还没有调用.start()启动。
就绪状态(Runnable)调用.start()方法,启动了该线程,等待CPU的调度。
运行状态(Running)获取到了CPU使用权,执行代码。
阻塞状态(Blocked)因为某种原因暂停运行,直到再次进入就绪状态。
死亡状态(Dead)线程执行完run方法自然死亡,或者在出现异常而死亡。
线程的创建有两种方法:
1.继承Thread类
2.实现Runnable接口
创建了线程之后并没有直接启动,调用 t.start() 方法之后才真正启动了线程。
这里需要注意的是线程的run()方法, t.run()和t.start()方法都能调用到线程内部的run()方法,但是t.run()方法调用的run()方法并不是在新创建的线程里执行的,而是被创建新线程的线程给执行了。
这里我在内部创建了10个线程,并且调用.run()方法,而不是.start()方法,所以打印出来的十个输出方法都是由main线程执行的。如果在这里调用.start()方法,就会输出每个线程的线程名,也就是各自执行的线程。
线程的创建顺序并不等于线程的执行顺序,线程的执行是无序的。
我在创建线程的时候是有序的创建的,而在线程执行的时候从输出台的语句可以看到并不是有序的。
·
多线程
多线程顾名思义就是多个线程同时存在。
多线程的优点是能够适当提高程序的执行效率和CPU利用率内存利用率等。但是大量的线程会占据一定的内存空间,并且CPU的使用也会加大。
多个线程对同一个对象执行操作会产生一些的错误,比如对同一个文件进行读写,所以在需要进行这些操作的线程前加上synchronized关键字来确保同一时刻只有一个线程能进行操作。
·
线程池
不断的进行线程的创建会造成内存溢出,利用线程池来管理线程可以限制线程的数量,并且回收再利用。
线程池的顶级接口是 Executor,不过真正的线程池接口是 ExecutorService, ExecutorService 的默认实现是 ThreadPoolExecutor。
Executors 提供四种线程池:
(1)newCachedThreadPool可缓存线程池,线程数量过多就回收空闲线程
(2)newFixedThreadPool 固定大小线程池,限定最大并发线程数,超过这个限定值就在队列中等待
(3)newScheduledThreadPool 大小无限线程池,支持定时及周期性任务执行
(4)newSingleThreadExecutor 单线线程池,只有一个线程串行处理所有任务,如果线程一场结束,会产生一个新线程
向线程池提交任务
execute(),向线程池提交一个任务
submit(),向线程池提交一个任务,并且返回该任务的执行结果
关闭线程
shutdown():关闭线程池,等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即关闭线程池,尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
线程
线程是操作系统能够进行运算调度的最小单位,线程被包含在进程中,一个进程至少包含一个线程,进程也可以并发的执行多个线程。
线程的生命周期:
新建状态(New) 新创建了一个线程,还没有调用.start()启动。
就绪状态(Runnable)调用.start()方法,启动了该线程,等待CPU的调度。
运行状态(Running)获取到了CPU使用权,执行代码。
阻塞状态(Blocked)因为某种原因暂停运行,直到再次进入就绪状态。
死亡状态(Dead)线程执行完run方法自然死亡,或者在出现异常而死亡。
线程的创建有两种方法:
1.继承Thread类
public class MyThread extends Thread { @Override public void run() { //重写run方法 //这里就是我们要在子线程中执行的操作 } }
MyThread t = new MyThread();
2.实现Runnable接口
public static class MyRunnable implements Runnable { public void run(){ //重写run方法 //这里就是我们要在子线程中执行的操作 } }
Thread t = new Thread(new MyRunnable());
创建了线程之后并没有直接启动,调用 t.start() 方法之后才真正启动了线程。
这里需要注意的是线程的run()方法, t.run()和t.start()方法都能调用到线程内部的run()方法,但是t.run()方法调用的run()方法并不是在新创建的线程里执行的,而是被创建新线程的线程给执行了。
public static void main(String[] args) { for(int i=0; i<10; i++){ final int count = i; new Thread("Thread_" + count){ public void run(){ System.out.println(count + " " + Thread.currentThread().getName() + " is running"); } }.run(); } }
这里我在内部创建了10个线程,并且调用.run()方法,而不是.start()方法,所以打印出来的十个输出方法都是由main线程执行的。如果在这里调用.start()方法,就会输出每个线程的线程名,也就是各自执行的线程。
线程的创建顺序并不等于线程的执行顺序,线程的执行是无序的。
public static void main(String[] args) { System.out.println(Thread.currentThread().getName() + " is running"); for(int i=0; i<10; i++){ final int count = i; new Thread("Thread_" + count){ public void run(){ System.out.println(Thread.currentThread().getName() + " is running"); } }.start(); } }
我在创建线程的时候是有序的创建的,而在线程执行的时候从输出台的语句可以看到并不是有序的。
·
多线程
多线程顾名思义就是多个线程同时存在。
多线程的优点是能够适当提高程序的执行效率和CPU利用率内存利用率等。但是大量的线程会占据一定的内存空间,并且CPU的使用也会加大。
多个线程对同一个对象执行操作会产生一些的错误,比如对同一个文件进行读写,所以在需要进行这些操作的线程前加上synchronized关键字来确保同一时刻只有一个线程能进行操作。
·
线程池
不断的进行线程的创建会造成内存溢出,利用线程池来管理线程可以限制线程的数量,并且回收再利用。
线程池的顶级接口是 Executor,不过真正的线程池接口是 ExecutorService, ExecutorService 的默认实现是 ThreadPoolExecutor。
Executors 提供四种线程池:
(1)newCachedThreadPool可缓存线程池,线程数量过多就回收空闲线程
(2)newFixedThreadPool 固定大小线程池,限定最大并发线程数,超过这个限定值就在队列中等待
(3)newScheduledThreadPool 大小无限线程池,支持定时及周期性任务执行
(4)newSingleThreadExecutor 单线线程池,只有一个线程串行处理所有任务,如果线程一场结束,会产生一个新线程
向线程池提交任务
execute(),向线程池提交一个任务
submit(),向线程池提交一个任务,并且返回该任务的执行结果
关闭线程
shutdown():关闭线程池,等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即关闭线程池,尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
相关文章推荐
- 省、市、县、镇、村数据库(PowerDesigner设计、BCP导入)
- idea 破解代码
- 梦断代码阅读笔记02
- 图片压缩工具类
- 第二阶段团队项目冲刺第一天
- linux网卡重启失败错误
- OpenTSDB 造成 Hbase 整点压力过大问题的排查和解决
- Android Studio2.0搭建NDK环境
- MVC JsonResult的用法
- Hadoop中mapred包和mapreduce包的区别与联系
- 男人的魅力
- 检测手机当前是否有网络
- linux驱动程序中的结构体成员前为什么有一个点“.”?
- 备忘
- 模拟Http登录
- WordPress 前端用户投稿插件 Frontend Publishing
- Ajax在PC端可以使用但在手机端不能使用
- 高并发金融应用架构优化与平台创新
- 23种设计模式(19)---Command模式
- Android中Fragment数据保存和恢复