Thread类

学习java线程的开发者,首先遇到的第一个类就是Thread,通过使用Thread类,我们就可以启动,停止,中断一个线程. 在同一个时间片里, 可能会有多个线程在执行, 每个线程都拥有它自己的方法调用堆栈, 参数和变量.每个app至少会有一个线程--主线程(main thread).

创建一个线程

java创建线程有两种方式

创建一个继承Thread的子类,并实现run方法

使用Thread的构造方法public Thread(Runnable target)创建,这个需要传入一个实现Runnable接口的子类

实现

下面我们分别以这两种方式实现一下.

编写SubThread继承Thread,并覆盖run方法 SubThread.java

public class SubThread extends Thread{

@Override

public void run() {

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

System.out.println(Thread.currentThread().getName() + ":" + i);

}

}

public static void main(String[] args) {

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

SubThread sub = new SubThread();

sub.start();

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

}

}

编写SubRunnable实现Runnable,然后使用构造器Thread(Runnable) 创建一个线程

public class SubRunnable implements Runnable {

@Override

public void run() {

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

System.out.println(Thread.currentThread().getName() + ":" + i);

}

}

public static void main(String[] args) {

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

Thread thread = new Thread(new SubRunnable());

thread.start();

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

}

}

区别

使用第一种方法创建的话,你可以在run方法中,可以用this直接调用线程的方法,比如获取线程的id-->this.getId()

而使用第二方法创建线程,在run中,this对象压根就没有getId()这个方法,这个时候你只能用Thread.cuurentThread()这个静态方法获取该线程.

在这里一般推荐使用第二种方法创建,因为这样比较符合面对象的思路,Thread就只负责线程的启动,停止,中断等操作,而Runnable就只负责线程要运行某一个具体任务.

不管使用那种方式创建线程,都可以调用Thread.cuurentThread()获取当前的线程

还有,Thread其实也是Runnable的一个子类

除了上面两种创建方法,其中还有另外一种方法创建线程,那就是实现ThreadFactory接口,这种比较适合批量生成某一种规格的线程

让线程"睡"一会

调用线程的Thread.sleep()方法会让线程睡眠一段时间,这个时候线程会挂起,然后将CPU的时间片转移给其他线程,让其他线程获得执行的机会.

Thread.sleep()接收一个毫秒值做完参数,并抛出一个InterruptedException异常.

停止线程

不管是使用哪一种方法创建线程,run方法的任务执行完了,线程就自动停止.

如果想在中途就停止线程,有下面几种方式

调用线程的interrupt()方法,这时线程的中断位会被标识,并抛出InterruptedException,例如:

public class StopThread1 {

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

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

Thread thread = new Thread(new Runnable() {

@Override

public void run() {

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

try {

Thread.sleep(100);

System.out.println(Thread.currentThread().getName() + ":" + i);

} catch (InterruptedException e) {

break;

}

}

}

});

thread.start();

System.out.println("main sleep 500ms");

Thread.sleep(500);

thread.interrupt();

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

}

}

在调用thread.interrupt();这个语句时,会对该线程的中断状态标识为true,然后在抛出InterruptedException异常时,会清空该中断位.

修改程序,在抛出InterruptedException中添加System.out.println("InterruptedException:" + Thread.currentThread().isInterrupted());,然后再thread.interrupt();后面添加System.out.println("thread.isInterrupted:" + thread.isInterrupted());.然后运行程序.

这时候运行结果有可能打印出thread.isInterrupted:true;InterruptedException:false或者打印出thread.isInterrupted:false;InterruptedException:false,运行多次结果都有可能不一致,这个是因为主线程和子线程都通知在执行,还没有来的及执行主线程的打印语句,子线程异常中的打印语句就已经执行了.

可以在线程中加一个boolean成员变量,提供setter方法,然后在run方法中判断该变量是否为true,若为true则停止线程,否则继续

public class StopThread2 {

public static class StopRunnable implements Runnable{

private boolean isStop = false;

public void setStop(){

this.isStop = true;

}

@Override

public void run() {

int count = 0;

while (!isStop){

try {

Thread.sleep(100);

System.out.println(Thread.currentThread().getName() + ":" + count++);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

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

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

StopRunnable stop = new StopRunnable();

Thread thread = new Thread(stop);

thread.start();

Thread.sleep(200);

stop.setStop();

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

}

}

线程的属性

id: 通过Thread.getId()可以获取线程的id,线程的id是一个自增长的long, 不能修改

name: 通过Thread.getName(), 用一个字符串来标识线程的名字,可以通过Thread.setName()或部分构造器修改线程的名字

priority: 线程的优先级,线程创建默认优先级为5, 最小为优先级为1, 最大为10.优先级大的线程有机会先执行.但具体那个线程先执行还是要看CPU的心情了.

state: 线程的状态, 线程的状态有以下几种

Thread.State.NEW: _新建状态_:这个是线程已经被创建但还没有调用'start()'方法时的状态

Thread.State.RUNNABLE: 运行状态 当前线程已经在JVM中执行

Thread.State.BLOCKED: 阻塞状态 表示当前线程在等待进入一个同步块或同步方法,也可以等到一个同步快被提交. 常见的有IO阻塞等.

Thread.State.WAITING: 等待状态 但线程调用Object.wait(),Thread.join(),LockSupport.park()就会进入等待状态.当前线程在等待其他线程执行某一个特定操作.比如:当前线程执行Object.wait(),那么就需要其他线程执行Object.notify()或Object.notifyAll(),如果线程执行了Thread.join(),则需要等到指定的线程执行结束.

Thread.State.TIMED_WAITING: 有时间的等待 线程在等待某一个等待的时间.比如,线程执行了Thread.sleep,Object.wait(long),Thread.join(long)等

Thread.State.TERMINATED: 终结 线程已经执行完毕.

daemon: 这个用来标识线程为守护线程或非守护线程的,默认创建的线程都是非守护线程.应用程序所有的非守护线程执行完毕之后,则程序就停止运行.比如主线程都是非守护线程,所以主线程会等到主线程的所有语句执行完成,程序才会停止运行.JVM的资源回收则是一个守护线程.

public class TestDaemonThread {

public static void main(String[] args) {

System.out.println("start main");

Thread thread = new Thread(new Runnable() {

@Override

public void run() {

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

try {

System.out.println(Thread.currentThread().getName() + ":" + i);

Thread.sleep(10);

} catch (Exception e) {

e.printStackTrace();

}

}

}

});

thread.start();

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

}

}

该例子中,程序必须等到主线程和子线程同时执行完成才会停止,因为默认创建的线程都是非守护线程,如果在thread.start();前加入thread.setDaemon(true);, 那么程序不会等子线程执行完才结束程序的.

Thread.join()

等到某线程执行完毕才开始执行,如果调用Thread.join(long)则表示等到某线程执行完毕或指定的超时时间结束后才开始执行

public class ThreadJoinTest {

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

Thread thread1 = new Thread(() -> {

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

try {

Thread.sleep(10);

System.out.println(Thread.currentThread().getName() + ":" + i);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}, "thread1");

Thread thread2 = new Thread(() -> {

try {

thread1.join();

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

Thread.sleep(10);

System.out.println(Thread.currentThread().getName() + ":" + i);

}

} catch (InterruptedException e) {

e.printStackTrace();

}

}, "thread2");

thread1.start();

thread2.start();

}

}

上面的例子,thread2线程会等thread1执行完之后才开始执行

Thread.yield

这个方法标识当前线程会按时线程调度者让其他线程先执行.但CPU是否让其他线程优先执行,还是要看CPU的心情了.

线程的异常

如果线程发现一些运行时异常而没有在run方法俘获,会怎么办?

程序会打印出一推错误堆栈,如果我们先把线程的错误按照某种可读的方式打印到问题,但又不想在每个run方法中增加try{...}catch(Exception e){...}怎么办?

我们查看Thread类的源码发现,在Thread中有一个内部接口UncaughtExceptionHandler,这个正是我们所需要的.实现这个接口,并调用Thread.setUncaughtExceptionHandler,那么但线程出现时,则会回调uncaughtException方法

public class ThreadExceptionTest {

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

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

Thread thread = new Thread(() -> {

int i = 1 / 0;

},"myThread");

thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

@Override

public void uncaughtException(Thread t, Throwable e) {

System.out.println(String.format("%s发生异常%s", t.getName(), e.getMessage()));

}

});

thread.start();

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

}

}

打赏

如果觉得我的文章写的还过得去的话,有钱就捧个钱场,没钱给我捧个人场(帮我点赞或推荐一下)

java new thread()_(一)java多线程之Thread相关推荐

  1. 稳扎稳打Silverlight(25) - 2.0线程之Thread, Timer, BackgroundWorker, ThreadPool

    [索引页] [源码下载] 稳扎稳打Silverlight(25) - 2.0线程之Thread, Timer, BackgroundWorker, ThreadPool 作者:webabcd 介绍 S ...

  2. (一)java多线程之Thread

    目录 Thread类 创建一个线程 java创建线程有两种方式 实现 区别 让线程"睡"一会 停止线程 线程的属性 Thread.join() Thread.yield 线程的异常 ...

  3. java thread类_java多线程之Thread类

    Class Thread java.lang.Object java.lang.Thread 实现接口:Runnable 直接被继承的子类:ForkJoinWorkerThread public cl ...

  4. java多线程阶乘_【java学习记录】11.用多线程实现阶乘的计算过程和结果的读取(thread类ReadThread )...

    (源码在上传的压缩包"[java学习记录]11.多线程实现阶乘计算(Thread类和Runnable接口)"中可看到,该压缩包可下载)java * 采用Thread类的子类实现线程 ...

  5. JAVA线程之Thread类详解

    Thread类用于操作线程,是所以涉及到线程操作(如并发)的基础.本文将通过源码对Thread类的功能作用进行分析. 一.属性 /* Make sure registerNatives is the ...

  6. java线程概念_《Java基础知识》Java线程的概念

    按照规划,从本篇开始我们开启『并发』系列内容的总结,从本篇的线程开始,到线程池,到几种并发集合源码的分析,我们一点点来,希望你也有耐心,因为并发这块知识是你职业生涯始终绕不过的坎,任何一个项目都或多或 ...

  7. java核心教程_核心Java教程

    java核心教程 Welcome to Core Java Tutorial. I have written a lot on Core Java and Java EE frameworks. Th ...

  8. java 分割一个_分割java

    [java]分割字符串工具类,霸气 jdk自带的 java 分割字符串,分割string,可以根据多个条件去分割.比如逗号,分号,逗号或者分号. 比如一个字符串:"abc,def;gh,ij ...

  9. java 画笔粗细_用JAVA做个画笔,有画笔和橡皮功能就行。越简单越好

    展开全部 新建一个java文件,取名叫做PaintJava.java 代码如下: import java.applet.*; import java.awt.*; import java.awt.ev ...

最新文章

  1. 关于模型复杂度的一个想法
  2. 如何求一个数的因数 c语言代码,【代码】求一个数的因数和、求优化、顺便也供新人参考算法...
  3. node.js 腾讯镜像站_使用腾讯云提供的针对Nuget包管理器的缓存加速服务
  4. 如何向Spring Bean 中注入java.util.Properties?
  5. S/4HANA for Customer Management里的搜索分页处理
  6. 一秒点击手机屏幕次数_手机电池不耐用,都怪这些充电坏毛病
  7. python 类中方法总结 --- 实例方法、类方法、静态方法
  8. Dying In The Sun
  9. MySQL数据库 : 基本语句
  10. ACR2010_常规医疗环境下TNF拮抗剂对RA骨侵蚀的修复作用
  11. 数据库errno: 1045的解决办法
  12. C++的学习(十)类和对象
  13. 阿里负载均衡,配置中间证书问题(在starcom申请免费DV ssl)
  14. 每日小记2012.5.1
  15. fedora安装java
  16. php 页面字体大小,CSS_做网页字体大小参考 网页中同字号字体的不同单位对比列表,对于WEB前端页面开发,字体大 - phpStudy...
  17. python pygame实现简单的网游 1
  18. 车辆模型-动力学模型(Dynamics Model)
  19. Windows系统远程桌面连接阿里云Linux Ubuntu
  20. 超声成像发射声场仿真(Ultrasound Emit Field Simulation)

热门文章

  1. 关于印发医疗卫生机构网络安全管理办法的通知
  2. STM32F767--LTC4015--SMBUS通信
  3. linux pscp 上传_windows与linux传输工具pscp详解
  4. 我用Python隐藏了MacBook Pro 14的大刘海
  5. Vue实现媒体文件下载
  6. 版本更新时出现解析包错误
  7. arduino麦轮转弯程序_Arduino 自动避障智能小车制作教程
  8. NVIDIA Jetson TX1(2)
  9. Android 12 关机确认提示弹窗超出屏幕或随分辨率大小比例改变的问题解决
  10. 概率统计之——方差分析