join线程

  • 假如A线程要B线程去完成一项任务,在B线程完成返回之前,不进行下一步执行,那么就可以调用B线程的join()方法
  • join()方法的重载:
    • join():等待不限时间
    • join(long millis):等待millis毫秒
    • join(long millis,int nanos):很少用,等待毫秒+毫微秒
  • 看示例:
package testpack;
public class Test2 {
public static void main(String[] args) throws InterruptedException{
System.out.println("现在线程是: "+Thread.currentThread().getName());
A a=new A();
Thread t1=new Thread(a,"被join线程");
t1.start(); //先start,后join
t1.join(); //调用join()方法
System.out.println("主线程执行完毕"); //主线程要等t1线程执行完毕,才执行这条语句;如果不调用join(),可能主线程执行完了这条语句,才会执行t1
}
}
class A implements Runnable{
public void run(){
for (int i=0;i<5;i++){
System.out.println(Thread.currentThread().getName()+" 输出: "+i);
}
}
}

后台线程

  • 后台线程,又叫守护线程,如果所有的前台线程都执行完毕,那么不论后台线程执行完毕与否,都直接进入死亡状态
  • 前台创建的子线程是前台线程,后台线程创建的子线程是后台线程
  • setDaemon(boolean on):是否将该线程设为后台(true)线程,该方法要在start之前调用,否则抛出IllegalThreadStateException异常
  • isDaemon():判断该线程是不是后台线程
  • 看示例:
package testpack;
public class Test2 {
public static void main(String[] args) throws InterruptedException{
Thread t=new Thread(new A(),"后台线程");
t.setDaemon(true); //start之前调用setDaemon方法
t.start();
for (int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+" output: "+i);
}
}
}
class A implements Runnable{
public void run(){
for (int i=0;i<50;i++){
System.out.println(Thread.currentThread().getName()+" 输出: "+i);
}
}
}

输出:

main output: 0

main output: 1

main output: 2

main output: 3

main output: 4

main output: 5

main output: 6

后台线程 输出: 0

main output: 7

后台线程 输出: 1

后台线程 输出: 2

后台线程 输出: 3

main output: 8

main output: 9

后台线程 输出: 4

后台线程 输出: 5 //后台线程本应执行到49,唯一的前台线程主线程结束后,后台线程也跟着死亡

线程sleep

  • sleep(long millis):
  • sleet(long millis,int nanos):
  • 该方法让线程暂停执行,交出cpu的执行权,,进入阻塞状态,不释放锁,醒来之后进入就绪状态,不一定能立刻得到执行,看线程调度
  • 示例:
package testpack;

import java.util.Date;

public class Test2  {
public static void main(String[] args) throws InterruptedException{
System.out.println("当前时间:"+new Date());
Thread.sleep(3000);
System.out.println("当前时间:"+new Date());
}
}

输出:

当前时间:Thu Dec 08 09:44:02 CST 2016

当前时间:Thu Dec 08 09:44:05 CST 2016 //主线程暂停执行3秒

线程yield

  • 线程让步,会使线程从运行状态进入就绪状态,不会进入阻塞状态,这时会让线程优先级相同或更高的线程执行
  • 示例
package testpack;
public class Test2 {
public static void main(String[] args) throws InterruptedException{
A a1=new A("线程 低");
A a2=new A("线程 中");
A a3=new A("线程 高");
a1.setPriority(Thread.MIN_PRIORITY);
a2.setPriority(Thread.NORM_PRIORITY);
a3.setPriority(Thread.MAX_PRIORITY);
a1.start();
a2.start();
a3.start();
}
}
class A extends Thread{
A(String name){
super(name);
}
public void run(){
for (int i=1;i<10;i++){
System.out.println(getName()+" 输出: "+i);
if (i==3){
Thread.yield();
}
}
}
}

输出:

线程 低 输出: 1

线程 高 输出: 1

线程 中 输出: 1

线程 高 输出: 2

线程 低 输出: 2

线程 高 输出: 3

线程 中 输出: 2

线程 高 输出: 4

线程 低 输出: 3 //低级线程输出3后,yield,下面让高线程执行

线程 高 输出: 5

线程 中 输出: 3 //中级线程输出3后,也yield,下面让高线程执行

线程 高 输出: 6

线程 高 输出: 7

线程 高 输出: 8

线程 高 输出: 9

线程 低 输出: 4

线程 中 输出: 4

线程 中 输出: 5

.......

sleep与yield的对比

  • sleep:运行->阻塞->就绪;yield:运行->就绪
  • sleep之后,其他线程不论优先级高低,都有可能得到执行;yield之后,只有平级或更高级的线程才会被执行
  • sleep声明了抛出InterruptedException异常,yield没有
  • sleep方法移植性更强,不建议用yield来控制并发线程的执行

线程优先级

  • 线程优先级可以是[1,10]的整数,由setPriority(int newPriority)设置
  • 三个优先级常量:MAX_PRIORITY、NORM_PRIORITY、MIN_PRIORITY。值分别是10、5、1
  • 每个线程的默认优先级跟创建它的父线程的优先级相同
  • 为了更好的可移植性,建议使用优先级常量,少用int优先级
  • 查看优先级:int getPriority()

线程组

  • 每个线程都处于一个线程组中,通过线程组,可以对一批线程进行批量控制
  • 如果没有指定线程组,那么处于默认线程组;子线程和创建它的父线程处于同一个线程组
  • 如果要指定一个线程的线程组,应在构造方法中指定,创建了线程实例后,不能改变线程组
  • 如何获得一个线程所属的线程组:getThreadGroup()
  • Thread的构造器中指定线程组
    • Thread(ThreadGroup group,Runnable target):
    • Thread(ThreadGroup group,Runnable target,String name):
    • Thread(ThreadGroup group,String name):
  • ThreadGroup的构造器
    • ThreadGroup(String name):以指定的名称、当前线程所属的线程组创建一个线程组
    • ThreadGroup(ThreadGroup parent, String name):以指定的名称、指定的父线程组创建一个线程组
  • ThreadGroup的几个方法
    • getName():返回该线程组的名字
    • 操作该线程组下的所有线程
      • int activeCount():返回此线程组中活动线程的数目
      • void interrupt():中断该线程组中的所有线程
      • boolean isDaemon():判断是不是后台线程组
      • void setDaemon(boolean daemon):设置为后台线程组,其中的最后一个线程死亡之后,该线程组销毁。特别注意:后台线程组下的线程可不都是后台线程,二者无关
      • void setMaxPriority(int pri):设置该线程组的最高优先级
System.out.println(Thread.currentThread());

输出:Thread[main,5,main]:第一个main是线程名;5是线程优先级;第二个main是所属线程组名

  • 示例:
package testpack;
public class Test2 {
public static void main(String[] args) throws InterruptedException{
System.out.println("主线程名: "+Thread.currentThread().getName()
+" ;所属线程组: "+Thread.currentThread().getThreadGroup().getName()
+" ;是不是后台线程?"+Thread.currentThread().isDaemon()); ThreadGroup tg=new ThreadGroup("后台线程组");
tg.setDaemon(true);
A a=new A(tg,"后台线程组的线程A");
a.start();
}
}
class A extends Thread{
A(ThreadGroup group,String name){
super(group,name);
}
public void run(){
System.out.println("线程名: "+getName()+" ;所属线程组:"+getThreadGroup().getName()+" ;是不是后台线程?"+isDaemon());
}
}

输出:

主线程名: main ;所属线程组: main ;是不是后台线程?false

线程名: 后台线程组的线程A ;所属线程组:后台线程组 ;是不是后台线程?false //后台线程组下的线程不一定是后台线程

其他

  • 最近发现一个做笔记的地方,蚂蚁笔记:https://leanote.com,支持Markdown,还可以把一篇笔记或一个笔记本公开为博客,可以绑定二级域名或者自定义域名,可以导出为PDF,支持团队协作,甚至是开源的,可以将其部署在自己的服务器上,是一个挺不错的应用
  • 本篇笔记也发布在leanote:在这里
  • 这是我的邀请链接,如果想注册,可以通过该链接,你我都可以获得30天的旗舰版时间

0039 Java学习笔记-多线程-线程控制、线程组的更多相关文章

  1. Java学习笔记-多线程-创建线程的方式

    创建线程 创建线程的方式: 继承java.lang.Thread 实现java.lang.Runnable接口 所有的线程对象都是Thead及其子类的实例 每个线程完成一定的任务,其实就是一段顺序执行 ...

  2. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  3. 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal

    什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...

  4. 0036 Java学习笔记-多线程-创建线程的三种方式

    创建线程 创建线程的三种方式: 继承java.lang.Thread 实现java.lang.Runnable接口 实现java.util.concurrent.Callable接口 所有的线程对象都 ...

  5. Java学习笔记-基础语法Ⅹ-进程线程

    学习快一个月了,现在学到了黑马Java教程的300集 打印流的特点: 只负责输出数据,不负责读取数据 有自己的特有方法 字节打印流:PrintStream,使用指定的文件名创建新的打印流 import ...

  6. java学习笔记 --- 多线程(多线程的创建方式)

    1.创建多线程方式1——继承Thread类. 步骤:  A:自定义类MyThread继承Thread类.  B:MyThread类里面重写run()? 为什么是run()方法呢? C:创建对象 D:启 ...

  7. java学习笔记 --- 多线程(1)

    1:要想了解多线程,必须先了解线程,而要想了解线程,必须先了解进程,因为线程是依赖于进程而存在. 2:什么是进程? 通过任务管理器我们就看到了进程的存在. 而通过观察,我们发现只有运行的程序才会出现进 ...

  8. 0040 Java学习笔记-多线程-线程run()方法中的异常

    run()与异常 不管是Threade还是Runnable的run()方法都没有定义抛出异常,也就是说一条线程内部发生的checked异常,必须也只能在内部用try-catch处理掉,不能往外抛,因为 ...

  9. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

随机推荐

  1. ABP(现代ASP.NET样板开发框架)系列之22、ABP展现层——导航栏设置

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之22.ABP展现层——导航栏设置 ABP是“ASP.NET Boilerplate Project (ASP.NE ...

  2. ubuntu 启动MySql和安装python的MySQLdb模块

    ubuntu一般会自己预安装mysql,你只需 /etc/init.d/mysql start|stop|restart|reload|force-reload|status  命令便可以实现mysq ...

  3. dhcp协议交互报文

    DHCP共有八种报文,分别为DHCP Discover.DHCP Offer.DHCP Request.DHCP ACK.DHCP NAK.DHCP Release.DHCP Decline.DHCP ...

  4. div里嵌套了img 底部会出现白边

    因为img默认是按基线(baseline)对齐的.对比一下图片和右边的p, q, y等字母,你会发现这三个字母的“小尾巴”和图片下方的空白一样高.下面这张图中的黑线就是那条基线. 要去掉空格可以使用v ...

  5. Java发展历史

    1991年1月 Sun公司成立了Green项目小组,专攻智能家电的嵌入式控制系统 1991年2月 放弃C++,开发新语言,命名为"Oak" 1991年6月 JamesGosling ...

  6. T-sql语句查询执行顺序

    前言 数据库的查询执行,毋庸置疑是程序员必备技能之一,然而数据库查询执行的过程绚烂多彩,却是很少被人了解,今天哥哥要带你装逼带你飞,深入一下这sql查询的来龙去脉,为查询的性能优化处理打个基础,或许面 ...

  7. PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式

    SPL(标准PHP库 - Standard PHP Library)是PHP5面向对象功能中重要的部分.原文解释是这样的“The Standard PHP Library (SPL) is a col ...

  8. lua解析赋值类型代码的过程

    我们来看看lua vm在解析下面源码并生成bytecode时的整个过程: foo = "bar" local a, b = "a", "b" ...

  9. DDD实践切入点(二)

    最近发现下面关于上下文的理解有些问题,不太好改,暂时先不改了 承前:大型系统的支撑,应用系统开发思想的变迁,DDD实践切入点(一) 从大比例结构入手已经开始了系统的建设,大家都知道需求是会不断变化不断 ...

  10. 从零开始编写自己的C#框架(17)——Web层后端首页

    后端首页是管理员登陆后进入的第一个页面,主要是显示当前登陆用户信息.在线人数.菜单树列表.相关功能按键和系统介绍.让管理员能更方便的找到息想要的内容. 根据不同系统的需要,首页会显示不同的内容,比如显 ...