@JunQiu
2019-10-30T16:43:18.000000Z
字数 4033
阅读 2555
language_java
进程&线程
summary_2019/10
## 线程创建
可以通过继承Thread类,或者实现Runnable接口,本身Thread类实现了Runnable接口,无论哪种方式都需要实现run方法。
(1)实现Runnable接口
public class MyThread implements Runnable {
private int count = 5;
@Override
public void run() {
//...
}
}
(2)继承Thread类
public class MyThread extends Thread {
@Override
public void run() {
//...
}
}
Tips: 关于Start方法
Thread.java 类中的 start() 方法通知“线程规划器”此线程已经准备就绪,等待调用线程对象的 run() 方法。这个过程其实就是让系统安排一个时间来调用 Thread 中的 run() 方法,也就是使线程得到运行,多线程是异步的,线程在代码中启动的顺序不是线程被调用的顺序。
1、线程安全:关于线程安全最通俗的理解就是,当使用多线程和单线程的结果相同时,那么可以说程序是线程安全的。
2、实例变量共享:变量是否共享的关键在于是否是使用的同一个对象。
3、synchronized关键字
## 实例1 - 实例变量共享
public class MyThread extends Thread {
private int count = 5;
@Override
public void run() {
super.run();
count--;
System.out.println("由 " + MyThread.currentThread().getName() + " 计算,count=" + count);
}
}
public class Run {
public static void main(String[] args) {
MyThread mythread=new MyThread();
// 通过同一对象创建线程,使用的是同一个对象,实例变量共享
Thread a=new Thread(mythread,"A");
Thread b=new Thread(mythread,"B");
Thread c=new Thread(mythread,"C");
Thread d=new Thread(mythread,"D");
Thread e=new Thread(mythread,"E");
a.start();
b.start();
c.start();
d.start();
e.start();
}
}
## 实例1 - 实例变量不共享
public class MyThread extends Thread {
private int count = 5;
public MyThread(String name) {
super();
this.setName(name);
}
@Override
public void run() {
super.run();
while (count > 0) {
count--;
System.out.println("由 " + MyThread.currentThread().getName()
+ " 计算,count=" + count);
}
}
}
public class Run {
public static void main(String[] args) {
MyThread a = new MyThread("A");
MyThread b = new MyThread("B");
MyThread c = new MyThread("C");
a.start();
b.start();
c.start();
}
}
3.1、 currentThread()
返回对当前正在执行的线程对象的引用。
3.2 getId()
返回此线程的标识符
3.3 getName()
返回此线程的名称
3.4 getPriority()
返回此线程的优先级
3.5 isAlive()
测试这个线程是否还处于活动状态。
什么是活动状态呢?
活动状态就是线程已经启动且尚未终止。线程处于正在运行或准备运行的状态。
3.6 sleep(long millis)
使当前正在执行的线程以指定的毫秒数“休眠”(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
3.7 interrupt()
中断这个线程。
3.8 interrupted() 和isInterrupted()
interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能
isInterrupted(): 测试线程Thread对相关是否已经是中断状态,但部清楚状态标志
3.9 setName(String name)
将此线程的名称更改为等于参数 name 。
3.10 isDaemon()
测试这个线程是否是守护线程。
3.11 setDaemon(boolean on)
将此线程标记为 daemon线程或用户线程。
3.12 join()
在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行
3.13 yield()
yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU时间。注意:放弃的时间不确定,可能一会就会重新获得CPU时间片。
3.14 setPriority(int newPriority)
更改此线程的优先级
## 正常情况下线程任务结束后,线程会自动停止,但是如果我们想手动结束进程我们可以采用下面的方法:
(1)stop(),suspend(),resume()这些方法已被弃用。
(2)interrupt()+ return
public class MyThread extends Thread {
@Override
public void run() {
try {
for (int i=0; i<50000; i++){
if (this.isInterrupted()) {
return 0;
}
System.out.println(i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
MyThread myThread =new MyThread();
myThread.start();
Thread.sleep(100);
myThread.interrupt();
}
}
(3)interrupt()+ 异常终止法
public class MyThread extends Thread {
@Override
public void run() {
try {
for (int i=0; i<50000; i++){
if (this.isInterrupted()) {
System.out.println(" 已经是停止状态了!");
throw new InterruptedException();
}
System.out.println(i);
}
System.out.println(" 不抛出异常,我会被执行的哦!");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
MyThread myThread =new MyThread();
myThread.start();
Thread.sleep(100);
myThread.interrupt();
}
}
## 设置线程优先级有助于帮“线程规划器”确定在下一次选择哪一个线程来优先执行。
1、线程优先级具有继承性,比如 A 线程启动 B 线程,则 B 线程的优先级与 A 是一样的。
2、线程优先级具有规则性,线程的优先级与在代码中执行 start() 方法的顺序无关,与优先级大小有关。
3、线程优先级具有随机性,CPU尽量使线程优先级较高的先执行完,但无法百分百肯定。即线程优先级较高的不一定比线程优先级较低的先执行完。
1、用户线程:运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程等都是用户线程
2、守护线程:运行在后台,为其他前台线程服务.也可以说守护线程是JVM中非守护线程的 “佣人”。
特点:一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作
应用:数据库连接池中的检测线程,JVM虚拟机启动后的检测线程
最常见的守护线程:垃圾回收线程
注意: setDaemon(true)必须在start()方法前执行,否则会抛出IllegalThreadStateException异常