我是靠谱客的博主 老迟到唇膏,最近开发中收集的这篇文章主要介绍Java并发编程(一)——线程Java并发编程(一)——线程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Java并发编程(一)——线程

一,线程的实现方式

  Java中实现多线程有两种方式,如下:

1,继承java.lang.Thread类,重写run()方法;
2,实现java.lang.Runnable接口,重写接口中的run()方法。

  这两种实现方式没有优劣,但由于Java中不允许多继承,所以使用第二种实现接口的方式更加灵活。
  另外需要注意的是实现了Runnable的类,就像其字面描述的意思一样,只是一个可运行的东西,最终也是要Thread类来启动它,它才能跑起来。这一点从源码上分析来看,只能说Runnable接口只是为了用来在不能多继承的情况下来实现多线程而设计的,最终线程的内容和启动还是Thread来实现的。
  代码如下:


public class ThreadDemo {
public static void main(String[] args) {
Thread t = new Thread();
t.start();
Thread t2 = new Thread(new Line());
t2.start();
}
}
class Line implements Runnable{
@Override
public void run() {
System.out.println("Line Thread is running...");
}
}

  而更多的情况下,我们会采用匿名内部类来实现多线程:


public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("I'm a new Thread");
}
}).start();
}

二,线程的生命周期

  线程的生命周期是指一个线程从创建到消亡的过程。

  • 新建状态(New)
      当用new操作符创建一个新的线程对象时,该线程处于创建状态。处于创建状态的线程只是一个空的线程对象,系统不为它分配资源。
    注意:不能对已经启动的线程再次调用start()方法,否则会出现java.lang.IllegalThreadStateException异常。如下:

Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("I'm a new Thread");
}
});
t.start();
t.start();//同一个(同id)线程不能同时启动两次

另,线程是不能clone的,因为线程id是不能重复的,会抛出CloneNotSupportedException异常,见源码:


@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
  • 就绪状态(Runnable)
      线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
  • 运行状态(Running)
      就绪状态的线程获取了CPU的使用权,执行程序代码的过程就处于运行态。
  • 阻塞状态(Blocked)
      阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
    (1)等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
    (2)同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
    (3)其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
  • 死亡状态(Dead)
      线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

三,线程状态的转换

1,线程生命周期图

这里写图片描述
这里写图片描述

2,线程状态的切换方式:

1)yield():yield的意思是让步,让出,就是暂时让出CPU的使用权,所以从Running变为了Runnable状态。
2)sleep():使线程睡眠一定的时间,由Running态变为Blocked态。
3)join():使当前线程(如主线程)挂起,直到调用join方法的线程执行完毕。
4)exit():在线程进入Running之前可以清空并退出该线程。
5)stop():强制线程退出,已废弃
6)suspend():挂起线程,由Running变为Blocked,和resume相对应,已废弃
7)resume():恢复线程,由Blocked变为Runnable,已废弃
8)interrupt():打断/中断线程。

四,Thread类的常用API

void setName(String name):为线程设置线程名;
  守护线程和用户线程的区别在于:守护线程依赖于创建它的线程,而用户线程则不依赖。举个简单的例子:如果在main线程中创建了一个守护线程,当main方法运行完毕之后,守护线程也会随着消亡。而用户线程则不会,用户线程会一直运行直到其运行完毕。在JVM中,像垃圾收集器线程就是守护线程。
void setDaemon(boolean on):设置是否是守护线程,是谁的守护线程?是当前线程的守护线程;需要在start方法调用之前使用;另,在Daemon线程中产生或新建的新线程默认也是Daemon的。

public class DaemonDemo {
public static void main(String[] args) throws InterruptedException {
TestThread test = new TestThread();
// 如果不设置daemon,那么线程将输出10后才结束
test.setDaemon(true);
test.start();
System.out.println("isDaemon = " + test.isDaemon());
try {
System.in.read(); // 接受输入,使程序在此停顿,一旦接收到用户输入,main线程结束,守护线程自动结束
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
class TestThread extends Thread {
public void run() {
for (int i = 1;; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println(i);
}
}
}

boolean isDaemon():判断是否是守护线程;
void setPriority(int newPriority):设置线程优先级,默认为5,最小为1,最大为10;优先级越高,越能更早的获取CPU调度;
Thread currentThread():返回当前线程对象的一个引用,为什么不用this?见下篇博客
int activeCount():返回当前线程所在的线程组中活跃线程的数量;

最后

以上就是老迟到唇膏为你收集整理的Java并发编程(一)——线程Java并发编程(一)——线程的全部内容,希望文章能够帮你解决Java并发编程(一)——线程Java并发编程(一)——线程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(85)

评论列表共有 0 条评论

立即
投稿
返回
顶部