多线程与线程池

多线程

基本相关概念

进程:是指计算机在执行的程序的实体。
线程:是指一个程序内部的顺序控制流。
进程与线程之间的关系:一个进程中可以包含一个或多个线程,一个线程就是一个程序内部的一条执行线索。
进程和线程的区别:
1.每个进程都有独立的代码和数据空间,进程的切换会有很大的开销。
2.同一类线程共享代码和数据空间,每个线程有独立运行的栈和程序计数器,线程切换的开销小。
多进程:在操作系统中能同时运行多个任务(程序)。
多线程:在同一应用程序中有多个顺序流同时执行。
并行:多个处理器或多核处理器同时处理多个任务。
并发:多个任务在同一个CPU核上,按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时进行的。
(并发和并行可以抽象的理解为:排队等咖啡,并发就是两个队列和一台咖啡机;并行就是两个队列和两台咖啡机。)

多线程实现的方式

实现多线程有三种方式:
1.继承Thread类,重写run()方法。
2.实现Runnable接口。
3.实现Callable接口。
注意:1.Runnable接口的run()方法没有返回值,Callable可以拿到返回值,所以Callable可以看做是Runnable的补充。
2.无论是实现Runnable接口还是Callable接口,在实例化实现类后,都要将实例化的对象注入到Thread类的有参构造中。也就是说还需要实例化Thread对象,只有Thread类下的start()方法才能使线程启动。

线程状态及其生命周期

线程的状态:
1.new 尚未启动
2.runnable 正在执行
3.blocked 阻塞的(被同步锁或者IO锁阻塞)
4.waiting 永久等待状态
5.timed-waiting 等待指定的时间重新被唤醒的状态
6.terminated 执行完成
线程的生命周期图:

图片1.jpg

线程类中的主要方法

图片3.jpg

注意:启动一个线程是调用 start()方法,使线程就绪状态,以后可以被调度为运行状态,一个线程必须关联一些具体的执行代码,run()方法是该线程所关联的执行代码。
sleep()和wait()有什么区别:
1.类的不同:sleep()来自Thread,wait()来自Object。
2.释放锁:sleep()不释放锁;wait()释放锁。
3.用法不同:sleep()时间到会自动恢复;wait()可以使用notify()/notifyAll()直接唤醒。
notify()和notifyAll()有什么区别:
1.notifyAll()会唤醒所有的线程,notify()之后唤醒一个线程。
2.notifyAll()调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。

线程的优先级

1.Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照线程的优先级来决定应调度哪个线程来执行。
2.Java线程的优先级用1~10的整数来表示,越小则优先级越低。(但是Java的优先级是高度依赖于操作系统的实现的)
Thread类的三个常量,表示常用的线程优先级:

Thread.MIN_PRIORITY   //1  
Thread.NORM_PRIORITY   // 5  
Thread.MAX_PRIORITY // 10  

缺省时线程具有NORM_PRIORITY

线程的终止

自动终止:一个线程完成执行后,不能再次运行
手动终止:
stop( ) —— 已过时,基本不用。
interrupt( ) —— 粗暴的终止方式
可通过使用一个标志指示 run 方法退出,从而终止线程。

线程同步

有时两个或多个线程可能会试图同时访问一个资源。例如,一个线程可能尝试从一个文件中读取数据,而另一个线程则尝试在同一文件中修改数据,在此情况下,数据可能会变得不一致。
为了确保在任何时间点一个共享的资源只被一个线程使用,使用了“同步”
当一个线程运行到需要同步的语句后,CPU不去执行其他线程中的、可能影响当前线程中的下一句代码的执行结果的代码块,必须等到下一句执行完后才能去执行其他线程中的相关代码块,这就是线程同步。
实现同步的两种方式:
1.将该方法用synchronized修饰。

synchronized void methodA() {
    ......
}

2.利用synchronized代码块。

synchronized (Object) {
 //要同步的语句
}

实现同步的两种方式的优缺点:
使用synchronized方法:
优点:可以显示的知道哪些方法是被synchronized关键字保护的。
缺点:方法中有些内容是不需要同步的,如果该方法执行会花很长时间,那么其他人就要花较多时间等待锁被归还;只能取得自己对象的锁,有时候程序设计的需求,可能会需要取得其他对象的锁。
使用synchronized代码块:
优点:可以针对某段程序代码同步,不需要浪费时间在别的程序代码上;
可以取得不同对象的锁。
缺点:无法显示的得知哪些方法是被synchronized关键字保护的。

线程池

线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。 例如,线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销。

线程池的创建方式

线程池创建有七种方式,最核心的是最后一种:
1.newSingleThreadExecutor():它的特点在于工作线程数目被限制为1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态,并且不允许使用者改动线程池实例,因此可以避免其改变线程数目。
2.newCachedThreadPool():它是一种用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置的时间超过 60 秒,则被终止并移出缓存;长时间闲置时,这种线程池,不会消耗什么资源。其内部使用 SynchronousQueue 作为工作队列。
3.newFixedThreadPool(int nThreads):重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有 nThreads 个工作线程是活动的。这意味着,如果任务数量超过了活动队列数目,将在工作队列中等待空闲线程出现;如果有工作线程退出,将会有新的工作线程被创建,以补足指定的数目 nThreads。
4.newSingleThreadScheduledExecutor():创建单线程池,返回 ScheduledExecutorService,可以进行定时或周期性的工作调度;
5.newScheduledThreadPool(int corePoolSize):和newSingleThreadScheduledExecutor()类似,创建的是个 ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。
6.newWorkStealingPool(int parallelism):这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序;
7.ThreadPoolExecutor():是最原始的线程池创建,上面1-3创建方式都是对ThreadPoolExecutor的封装。

线程池的状态

RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务。
SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务。
STOP:不接受新的任务提交,不再处理等待队列中的任务,中断正在执行任务的线程。
TIDYING:所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()。
TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。

线程池中 submit() 和 execute() 方法的区别

execute():只能执行 Runnable 类型的任务。
submit():可以执行 Runnable 和 Callable 类型的任务。
Callable 类型的任务可以获取执行的返回值,而 Runnable 执行无返回值。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358