Java多线程的常用方法基本分为:获取当前线程的操作,线程休眠sleep()方法,线程让步yield()方法,等待其他线程终止join()方法,线程停止的一系列方法。

一、获取当前线程的操作

  1、获取当前线程: Thread.currentThread();

    需要注意的是: 当一个线程A开启后,调用其他线程类B的普通方法时,此时的线程还是线程A, 当一个线程A直接调用另一个线程类B的run()方法,就和调用普通方法没有区别。

  举个栗子说明run()和start()有十分明显的区别

package com.xiaoaxiao.test.thread_test.book_test;

/**

* Created by xiaoaxiao on 2019/7/16

* Description: run()和start()不一样!!!

*/

class MyThread1 extends Thread{

@Override

public void run() {

try {

System.out.println("run threadName="+Thread.currentThread().getName()+" begin");

Thread.sleep(2000);

System.out.println("run threadName="+Thread.currentThread().getName()+" end");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public class ThreadTest2 {

public static void main(String[] args) {

MyThread1 mt = new MyThread1();

System.out.println("begin ="+System.currentTimeMillis());

//        mt.run();

mt.start();

System.out.println("end ="+System.currentTimeMillis());

}

}

若调用mt.run(),输出结果为:

begin =1563329164153

run threadName=main begin

run threadName=main end

end =1563329166155

若调用mt.start(),输出结果为:

begin =1563329194123

end =1563329194124

run threadName=Thread-0 begin

run threadName=Thread-0 end

  2、获取当前线程的名字:Thread.currentThread().getName()

   而获取当前对象的名字(只在Thread的继承类中出现):this.getName()

  3、获取当前线程的唯一标识:Thread.currentThread().getId()

二、线程休眠sleep()方法—单位为毫秒(ms)

  线程休眠是指 让当前线程暂缓执行,等到了预计时间后再恢复执行。线程休眠会立即交出CPU,但是不会释放锁。

  sleep()的流程:运行状态->sleep()->阻塞状态->sleep()的时间结束后->就绪状态->系统调度->运行状态。

   虽然sleep()在指定时间可以从运行状态->(阻塞状态)->就绪状态,但是处于就绪状态时,需要经过系统的调度才能到达运行状态,具体的系统调度是随机的(由CPU进行控制),这就导致了每次sleep()的时间不相同(是有差异的)。

  sleep()可能会抛出InterruptedException受查异常,需要对异常进行处理。

  sleep()立即交出CPU,不会释放锁。

  举个栗子

package com.xiaoaxiao.test.thread_test;

/**

* Created by xiaoaxiao on 2019/7/12

* Description: 测试thread常用的方法——sleep、

*/

class MyRunnable2 implements Runnable{

@Override

public void run() {

for(int i=0;i<3;i++){

System.out.println(Thread.currentThread().getName());

// sleep()

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

public class threadMethodTest1 {

public static void main(String[] args) {

MyRunnable2 myRunnable2 = new MyRunnable2();

Thread thread1 = new Thread(myRunnable2,"A");

//        Thread thread2 = new Thread(myRunnable2,"hello");

Thread thread2 = new Thread(myRunnable2,"B");

Thread thread3 = new Thread(myRunnable2,"C");

thread1.start();

thread2.start();

thread3.start();

}

}

输出结果:

B

C

A

A

C

B

B

C

A

三、线程让步yield()方法——运行态(running)->就绪态(runnable)

  线程让步是指 暂停执行当前的线程对象,并执行其他线程,yield()方法会让当前线程交出CPU(不一定立即交出CPU),不会释放锁。

  yield()方法无法控制具体交出CPU的时间,并且yield()方法只能让拥有相同优先级的线程有获取CPU的机会

  yield()会交出CPU(不一定立即交出),不会释放锁。

  举个栗子

package com.xiaoaxiao.test.thread_test;

/**

* Created by xiaoaxiao on 2019/7/12

* Description: 测试thread常用的方法——yield

*/

class MyRunnable2 implements Runnable{

@Override

public void run() {

for(int i=0;i<10;i++){

System.out.println(Thread.currentThread().getName());

// yield()

Thread.yield();

}

}

}

public class threadMethodTest1 {

public static void main(String[] args) {

MyRunnable2 myRunnable2 = new MyRunnable2();

Thread thread1 = new Thread(myRunnable2,"A");

Thread thread2 = new Thread(myRunnable2,"B");

Thread thread3 = new Thread(myRunnable2,"C");

thread1.start();

thread2.start();

thread3.start();

}

}

输出结果:

A

A

A

B

B

C

C

C

B

四、等待其他线程终止join()方法

  等待其他线程终止是指主线程等待子线程执行完成之后再结束。(主线程(或者某个线程)中若调用了子线程(或者是另外一个线程)的join()方法就必须得等该子线程run()方法结束,主线程才能继续执行)

   join()方法只是对外汇代理Object提供的wait()做了一层包装而已。 (join在内部使用wait()方法进行等待),执行wait(long)方法后,当前线程的锁会被释放,其他线程就可以调用此线程中的同步方法了。

   join()方法的执行流程与sleep()类似:运行状态->join()->阻塞状态->join()中断->就绪状态->系统调度->运行状态。

  join()可能会抛出InterruptedException受查异常,需要对异常进行处理。

  join()会释放锁。

  举个栗子

package com.xiaoaxiao.test.thread_test;

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.util.Date;

/**

* Created by xiaoaxiao on 2019/7/12

* Description: 测试thread常用的方法——join

*/

class MyRunnable3 implements Runnable{

@Override

public void run() {

try {

System.out.println("主线程睡眠前时间");

threadMethodTest2.printTime();

Thread.sleep(1000);

System.out.println(Thread.currentThread().getName());

System.out.println("睡眠结束时间");

threadMethodTest2.printTime();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public class threadMethodTest2 {

public static void main(String[] args) throws InterruptedException {

MyRunnable3 myRunnable3 = new MyRunnable3();

Thread threadA = new Thread(myRunnable3,"子线程A");

System.out.println("代码开始");

threadA.start();

// 调用子线程的join方法,当主线程执行到这一步了,

// 一定会等到子线程中所有内容全部执行完,主线程才会继续往下执行

threadA.join();

System.out.println(Thread.currentThread().getName());

System.out.println("代码结束");

}

public static void printTime(){

Date date = new Date();

DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String time = format.format(date);

System.out.println(time);

}

}

输出结果为:

代码开始

主线程睡眠前时间

2019-09-27 16:56:26

子线程A

睡眠结束时间

2019-09-27 16:56:27

main

代码结束

  还可以使用join(long)设置最长等待时间(单位:ms),若主线程等待long秒后,无论子线程会不会结束,此时join()中断,主线程进入就绪状态。

class Join extends Thread{

@Override

public void run() {

try {

System.out.println("begin Timer="+System.currentTimeMillis());

Thread.sleep(5000);

System.out.println("end Timer="+System.currentTimeMillis());

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

public class JoinTest {

public static void main(String[] args) {

Thread thread = new Join();

thread.start();

try {

thread.join(2000);

System.out.println("main end Timer:"+System.currentTimeMillis());

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

// 打印结果

begin Timer=1569575039934

end Timer=1569575041934

main end Timer:1569575041934

五、线程停止的一系列方法

  1、设置标记位(flag)停止线程——推荐(好写)

   在线程类内部设置一个标记位flag并由这个flag对线程类的执行进行控制,在线程类的外部对flag进行修改,从而实现外部对类内部的停止。

package com.xiaoaxiao.test.thread_test;

/**

* Created by xiaoaxiao on 2019/7/12

* Description: 测试thread常用的方法——线程停止-设置标记符

*/

class MyRunnable4 implements Runnable{

// 设置一个标记符

private Boolean flag = true;

@Override

public void run() {

int i=1;

// 将该标记符当做线程持续进行的条件

while (flag){

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("这是第"+i+"次执行"+"线程名称为:"

+Thread.currentThread().getName());

i++;

}

}

public void setFlag(Boolean flag) {

this.flag = flag;

}

}

public class threadMethodTest3 {

public static void main(String[] args) throws InterruptedException {

MyRunnable4 myRunnable4 = new MyRunnable4();

Thread thread = new Thread(myRunnable4);

thread.start();

Thread.sleep(5000);

// 主线程睡眠5s后将flag设置为false,

// 当子线程再次访问是,flag已经变为false

myRunnable4.setFlag(false);

// 调用子线程的join,让主线程等待子线程执行完成后再执行

thread.join();

System.out.println("代码结束");

}

}

2、调用Thread类的stop()方法强制停止线程,该方法不安全,已经被Deprecated(废弃)了。

  该方法之所以不安全主要是会造成数据的不一致。

while(flag){          //按照第一种停止方式,即便在x=3后,flag变为了false,

//y依旧能被赋值为4

x=3;

y=4;

}                      //而如果在x=3后直接stop(),则y就不会被赋值为4了

3、调用Thread类的interrupt()方法——系统设置标志位

①interrupt()方法只是将线程状态置为中断状态而已,它不会中断一个正在运行的线程,此方法只是给线程传递一个中断信号,程序可以根据此信号来判断是否需要终止。(使用isInterrupted()判断中断状态)

②当线程中使用wait()、sleep()、join()导致此线程阻塞,则interrupt()会在线程中抛出InterruptException,并且将线程的中断状态由true置为false。

PS:无论是在sleep()过程中,interrupt(),还是在interrupt()过程中,sleep(),都会抛出InterruptedException异常,并将interrupt中断状态置为false(sleep()和interrupt只要相遇就会出异常,其他两者同理)

③interrupt()中断线程

a)线程中没有wait(),sleep(),join(),调用interrupt只是将线程中断状态设置为true。

b)线程中有wait(),sleep(),join(),调用interrupt会抛出InterruptException并将线程中断状态由true置为false,在catch块中捕获该异常,然后退出

  举个栗子,sleep()对interrupt()的影响

package com.xiaoaxiao.test.thread_test.book_test;

/**

* Created by xiaoaxiao on 2019/7/16

* Description: sleep()对Interrupt()的影响

*              无论是在sleep()过程中,interrupt()

*              还是在interrupt()过程中,sleep()

*              都会抛出InterruptedException异常,并将interrupt状态置为false

*/

class MyThread2 extends Thread{

@Override

public void run() {

super.run();

try {

for(int i=0;i<1000000;i++){

System.out.println("i="+(i+1));

}

System.out.println("run begin");

Thread.sleep(200000);

System.out.println("run end");

} catch (InterruptedException e) {

System.out.println("先停止,再遇到sleep,interrupt状态为:"

+this.isInterrupted());

e.printStackTrace();

}

}

}

public class InterruptTest {

public static void main(String[] args) {

MyThread2 mt = new MyThread2();

mt.start();

mt.interrupt();

System.out.println("end!");

}

}

————————————————

原文链接:https://blog.csdn.net/weixin_43490440/article/details/96202420

Java多线程常用方法的使用的更多相关文章

  1. Java多线程中的常用方法

    本文将带你讲诉Java多线程中的常用方法   Java多线程中的常用方法有如下几个 start,run,sleep,wait,notify,notifyAll,join,isAlive,current ...

  2. Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗

    在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...

  3. Java多线程干货系列—(一)Java多线程基础

    前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...

  4. Java多线程总结之线程安全队列Queue

    在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列.Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非 ...

  5. Java多线程干货系列(1):Java多线程基础

    原文出处: 嘟嘟MD 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程 ...

  6. Java多线程学习(转载)

    Java多线程学习(转载) 时间:2015-03-14 13:53:14      阅读:137413      评论:4      收藏:3      [点我收藏+] 转载 :http://blog ...

  7. Java多线程编程详解

    转自:http://programming.iteye.com/blog/158568 线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Ja ...

  8. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

  9. 【转】 Java 多线程之一

    转自   Java 多线程 并发编程 一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进 ...

随机推荐

  1. 使用aop和BindingResult进行参数验证

    1.在需要校验的参数名上面添加注解 2.在web层接收参数(参数前面使用@Valid进行标记,后面必须紧跟参数bindingResult,存储参数的错误信息) 3.使用aop进行校验信息统一处理 @C ...

  2. mongodb增删改查基础语法

    转载:https://blog.csdn.net/u012206617/article/details/91047239 1. use DataBaseName 切换/创建数据库use mydb 2. ...

  3. postgres服务相关语法

    远程登陆 psql -h 主机 -U 用户 -p端口 -W -d 数据库 #-W表示密码,例如:psql -h 192.168.137.3 -U postgres -p 5432 -W -d post ...

  4. vue-cli脚手架快速搭建项目

    前言 vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目. 准备工作 在搭建一个vue项目之前,需要先安装好node.js和cnpm. 虽然np ...

  5. shell--grep命令+正则表达式+基本语法

    什么是正则 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则. 在linux中,通配符是由shell解释的,而正则表达式则 ...

  6. Sqli labs系列-less-5&6 报错注入法(上)

    在我一系列常规的测试后发现,第五关和第六关,是属于报错注入的关卡,两关的区别是一个是单引号一个是双引号...当然我是看了源码的.... 基于报错注入的方法,我早就忘的差不多了,,,我记的我最后一次基于 ...

  7. vue 微信公众号分享后支付失效页面URL不变的坑

    微信分享后支付页面还是初始页面,这个问题解决了, created(){ //判断是否是IOS设备 // IOS分享时的页面是首页,也就是进入页而不是当前页.所有可以采用刷新当前页,让进入页的链接改成当 ...

  8. 【从0到1,搭建Spring Boot+RESTful API+Shiro+Mybatis+SQLServer权限系统】01、环境准备

    开发环境 windows+STS(一个针对Spring优化的Eclipse版本)+Maven+SQLServer 环境部署 1.安装SQLServer(使用版本2008R2) 自行安装,此处略过 2. ...

  9. Could not open lock file/var/lib/dpkg/lock的解决

    Could not open lock file/var/lib/dpkg/lock的解决 在ubuntu系统中利用apt-get install something的时候,有时候会出现无法获得锁的权 ...

  10. MySQL高级学习笔记(六):MySql锁机制

    文章目录 概述 定义 生活购物 锁的分类 从对数据操作的类型(读\写)分 从对数据操作的粒度分 三锁 表锁(偏读) 特点 案例分析 建表SQL 加读锁 加写锁 结论 如何分析表锁定 行锁(偏写) 特点 ...