上一篇讲解了线程与线程池创建的一些方法,这期讲线程常用方法与线程池之间的区别。

上一篇中实现线程有继承Thread与实现Runnable接口两种。这里建议用Runnable,因为接口可以实现多继承,且只有一个run方法。

start方法与run方法:

start方法来启动线程,真正的实现了多线程,因为这是无需等待run()方法体里的代码是否执行完毕,它会继续执行下面的代码。当启动了start方法,就启动了一个线程,线程处于就绪状态,直到得到cpu时间片,就会执行run方法。当run方法体运行结束,这个线程也就结束。

run方法只是一个普通的方法,run方法体里面写了要执行的内容,直接调用run方法,程序中也只是有主线程一个线程,仍需等待run方法里面的方法体执行完毕后,才能继续执行下面的代码。这样就是去了并发的意义。

总结:start方法会开辟一条新线程,并且只能被调用一次(因为一个线程只能被初始化一次),当调用start时,线程会进入就绪阶段,当初始化完毕jvm会自动调用run方法来执行run方法里面的方法体。而run方法是由jvm直接调用的,他只是一个普通方法。如果我们没用启动线程(调用start),直接调用run方法,这样并不会开辟新的线程,而是运行在当前的线程中(即run方法所在的线程中),这样就违背了创建线程的初衷。

用户线程和守护线程的区别
二者其实基本上是一样的。唯一的区别在于JVM何时离开。

用户线程:当存在任何一个用户线程未离开,JVM是不会离开的。

守护线程:如果只剩下守护线程未离开,JVM是可以离开的。

常用方法:

getId():获取线程的id
getName():获取线程的名字
t.getPriority():获取线程优先级
t.isAlive():判断是否处于活跃状态
t.isDaemon()):是否为守护线程

getState():获取线程状态

isinterrupted:判断线程是否中断

setPriority():设置线程优先级

interrupt:用于中断线程,抛出interrupted异常

jion:如果当前线程中调用线程对象join,当前线程阻塞,直到线程对象的run执行完毕,当前线程阻塞结束。

wait: 当执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放锁,使得其他线程能够被访问,可以通过notify和notifyAll方法来唤醒。

yield:暂停当前执行的线程对象,并执行其他线程。就是当前线程交出cpu权限,让cpu及执行其他线程。不释放锁

sleep:当调用sleep方法时,会暂时让出cpu的执行权,等到时间到时会重新获得执行权,不会释放锁。

yield与sleep区别:yield不能控制具体的交出时间,并且yield只能让相同优先级的线程获取被cpu执行的机会,yield不会进入阻塞状态,而是就绪状态。

synchronized:同步监视器(俗称锁)

当两个并发的线程访问同一个对象中的这个加锁同步代码块时,同一时刻最多只有一个线程能执行这段代码。

下面我们来看一个案例:

众所周知:试衣间是不能两个异性同时进的!!!我们模拟两个人不认识的人同一时间在商场购买衣服,而商场只有一个试衣间。

public class Demo10 {static Object o=new Object();public static void main(String[] args) {Thread t=new Thread("杨过"){public void run(){shoping(Thread.currentThread().getName());}};Thread t1=new Thread("容么么"){public void run(){shoping(Thread.currentThread().getName());}};t.start();t1.start();}public  static void shoping(String name){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(name+"进入商场");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(name+"开始挑衣服");synchronized (o) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(name + "进入试衣间");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(name + "走出试衣间");}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(name+"结账走人");}
}

运行结果:

我们在试衣间部分上了锁也就是说,这两个进程不能同时访问试衣间的那段代码,必须要等一个线程执行完毕后另一个线程才能执行。也就是说这两个线程并发,两个线程执行什么,执行快慢都可以,但到了加锁同步代码块时,另一个线程必须等待那段代码执行完毕,另一个线程才能访问那段代码块。

CountDownLatch与CyclicBarrier:

CountDownLatch:

CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0时,await()方法会阻塞程序继续运行。CountDownLatch能够使一个线程等待其他线程完成各自的工作后再执行。

public class Demo10 {public static void main(String[] args) {CountDownLatch cdl=new CountDownLatch(3);Thread t1=new Thread(){public  void  run(){System.out.println(Thread.currentThread().getName()+"开始");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"完毕");cdl.countDown();}};Thread t2=new Thread(){public  void  run(){System.out.println(Thread.currentThread().getName()+"开始");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"完毕");cdl.countDown();}};Thread t3=new Thread(){public  void  run(){System.out.println(Thread.currentThread().getName()+"开始");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"完毕");cdl.countDown();}};Thread thread=new Thread(){public void run(){try {cdl.await();//等待阻塞   其他线程全部执行完毕} catch (InterruptedException e) {e.printStackTrace();}System.out.println("火箭发射。。。。");}};thread.start();t1.start();t2.start();t3.start();}
}

运行结果:

可以看到三个线程都结束后,最后的线程才执行。

CyclicBarrier:

CyclicBarrier的字面意思是可循环使用的屏障。它要做的事情是让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所以被屏障拦截的线程才会继续干活。每个线程调用await方法告诉CyclicBarrier我已经到达屏障,然后当前线程被阻塞。

public class Demo11 {public static void main(String[] args) {CyclicBarrier c=new CyclicBarrier(5);for (int i=0;i<11;i++){try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}Thread t=new Thread(){public void run(){System.out.println(Thread.currentThread().getName()+"来了");try {c.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"走了");}};t.start();}}
}

运行结果:(太长了没截图。)

Thread-0来了
Thread-1来了
Thread-2来了
Thread-3来了
Thread-4来了
Thread-4走了
Thread-0走了
Thread-1走了
Thread-3走了
Thread-2走了
Thread-5来了
Thread-6来了
Thread-7来了
Thread-8来了
Thread-9来了
Thread-9走了
Thread-5走了
Thread-7走了
Thread-8走了
Thread-6走了
Thread-10来了

以上我们可以看到只有当线程到达5的时候才会继续执行,而当运行到Thread-10时循环到达最大次数,没有新的进程加入,所以不会继续执行了。

CountDownLatch与CyclicBarrier区别:
       CountDownLatch:一个线程或者多个线程,等待另外N个线程完成某个事情之后才能执行。只有一个等待线程,其他N个线程都可以顺利执行完毕。(可以简单理解为发射火箭,必须等待其他工作完成才能发射)

CyclicBarrier:N个线程互相等待,任何一个线程完成之前,所有线程都必须等待。在最后一个未await之前,所有N个线程都不算完成,都处于阻塞状态。(可以简单理解为运动会百米赛跑,必须达到一定人数,裁判才会开枪)

java 线程(二)线程常用方法相关推荐

  1. C#中的线程(二) 线程同步基础

    1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...

  2. Java多线程学习(二)---线程创建方式

    线程创建方式 摘要: 1. 通过继承Thread类来创建并启动多线程的方式 2. 通过实现Runnable接口来创建并启动线程的方式 3. 通过实现Callable接口来创建并启动线程的方式 4. 总 ...

  3. java 线程转储_获取Java线程转储的常用方法(推荐)

    1. 线程转储简介 线程转储(Thread Dump)就是JVM中所有线程状态信息的一次快照. 线程转储一般使用文本格式, 可以将其保存到文本文件中, 然后人工查看和分析, 或者使用工具/API自动分 ...

  4. 使用匿名内部类实现方式二线程创建 java 1615474836

    使用匿名内部类实现方式二线程创建 java 1615474836 有点多余的类 匿名内部类的应用 代码改造 测试类中直接用匿名内部类 就可以不用单独的新建上述那个只用一次的类了 最终代码

  5. java中的线程及常用方法

    2.8 线程 2.8.1 线程的概念 程序:保存在物理介质中的代码片段 进程:正在进行当中的程序,就是操作系统的一个进程 线程:一个程序当中一条独立的执行线索 ​ 作用:只为让在同一时间做多件事,应对 ...

  6. JavaSE基础二十:Java 多线程(线程基础知识、Java 多线程、Java 实现多线程(继承 Thread 类、实现 Runnable 接口、实现 Callable 接口))

    本章目录 1.基础知识准备 2.Java 多线程概述 3.Java 实现多线程 3.1.继承 Thread 类 如何开启新线程 Thread 类常用方法 多线程中的同步 Thread 类同步方法 多线 ...

  7. 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...

  8. java线程中的常用方法_[多线程] 线程中的常用方法-最详细

    线程中常用的方法 1.public void start() 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 2.public void run() 如果该线程是使用独立的 Runna ...

  9. java多线程总结二:后台线程(守护线程)

    所谓的后台线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分.因此当所有的非后台线程结束时,程序也就终止了,同时会杀死所有后台线程.反过来说,只要有任何非 ...

  10. 【java笔记】线程(3):Thread类的常用方法

    [JAVA笔记]线程(1):多线程的介绍和实现_m0_52043808的博客-CSDN博客 [java笔记]线程(2):多线程的原理_m0_52043808的博客-CSDN博客 获取线程的名称: St ...

最新文章

  1. 零基础Java学习之初级项目实践(客户信息管理软件-附源码)
  2. 【Laravel】连接 sqlite 数据库 Database [xxx] not exist
  3. SQL update select结合语句详解及应用
  4. c语言memset清空指向数组的指针_C语言中数组和指针的关系
  5. 发票二维码扫描增强_03_图像预处理_01_图像切片
  6. win10切换输入法快捷键_输入法失灵怎么办?该怎么恢复?
  7. c++远征之模板篇——标准模板库(STL)
  8. ot协议是什么_OT的完整形式是什么?
  9. [转载] 使用openpyxl模块向Excel中插入图片
  10. Collectors.toMap()
  11. 魔兽争霸显示无法登录服务器,魔兽登陆不上去_网络一切正常,但是魔兽世界就是登不上去...
  12. Arch + i3wm + i3lock-wrapper 毛玻璃锁屏
  13. Mac IntelliJ IDEA 2017.3.2破解方法
  14. 不要迷恋哥,哥只是个传说 - 生活至上,美容至尚!
  15. Cython优化简介
  16. 搜索引擎推广公司引擎推广方法及技巧
  17. 那些会讲ppt的技术人有多爽?演讲的6个步骤
  18. 【NOIP2016提高A组集训第12场11.10】灵知的太阳信仰
  19. linux系统忘记登录密码怎么办
  20. 应届毕业生工作7个月小结

热门文章

  1. 无法找到vcredist.msi
  2. MySQL百万级数据大分页查询优化
  3. U盘启动ubuntu出现黑屏下划线
  4. AI设计:如何给动作游戏的敌人设计人工智能?
  5. 【客户机操作系统已禁用 CPU。请关闭或重置虚拟机】以及【该主机 CPU 类型不支持虚拟化性能计数器,模块“VPMC”启动失败,未能启动虚拟机】
  6. Prometheus 基于文件的服务发现 file_sd_configs
  7. 三星VS苹果 平板行业的既生瑜何生亮
  8. WLAN组网AC间漫游
  9. 二进制转换为其他进制
  10. Agisoft Metashape 空三导入inpho(带连接点和控制点)