Java多线程编程一(一些线程的知识)

进程和线程的概念及线程的优点

进程:可简单理解为Window上的一个应用程序如:qq.exe
线程:可简单理解为qq.exe中的一个后台下载程序等

线程的优点:在同一时间可以同时进行多个任务的工作,很方便,高效率的节省工作时间。如你在聊q的同时,听歌,下载文件,聊天。。。

使用多线程

(1)继承Thread类重写run()方法:

1
2
3
4
5
6
7
8
9
10
11
12
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("需要执行的任务");
}
public static void main(String[] args) {
Thread thread = new MyThread();
thread.start();
System.out.println("运行结束!");
}
}

(2)实现Runnable接口:

1
2
3
4
5
6
7
8
9
10
11
public class MyThread implements Runnable {
public void run() {
System.out.println("需要执行的任务");
}

public static void main(String[] args) {
Thread thread = new Thread(new MyThread());
thread.start();
System.out.println("运行结束!");
}
}

实例变量和线程安全

自定义的线程类中实例变量针对其他线程可以有共享和不共享之分,这在多个线程之间进行交互时是个重要的技术点。

不共享数据的情况下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class MyThread extends Thread {

private int count = 5;

public MyThread(String name) {
this.setName(name);
}

@Override
public void run() {
System.out.println("需要执行的任务");
while (count > 0) {
count--;
System.out.println("由:" + Thread.currentThread().getName() + "计算,count=" + count);
}
}

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();
System.out.println("运行结束!");
}
}

由于每个实例都有属于自己的变量count,计算互不干扰,既不共享数据,所有也就不会出现错误数据的情况,是线程安全的。

共享数据的情况下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MyThread extends Thread {
private static int count = 5;

@Override
public void run() {
System.out.println("需要执行的任务");
while (count > 0) {
count--;
System.out.println("由:" + Thread.currentThread().getName() + "计算,count=" + count);
}
}

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");
a.start();
b.start();
c.start();
System.out.println("运行结束!");
}
}

运行结果:

1
2
3
4
5
6
7
8
9
需要执行的任务
需要执行的任务
由:A计算,count=3
由:B计算,count=3
由:A计算,count=1
由:B计算,count=1
由:A计算,count=0
运行结束!
需要执行的任务

由结果我们发现,出现了线程A和线程B取出的值为同一个值,产生了非线程安全的问题。在JVM中,i--分为如下三步:

    1. 取得原有值i
    1. 计算i-1
    1. 对i进行赋值

在这三个步骤中,如果有多个线程同时访问,那么一定会出现非线程安全问题

部分常用方法

  • currentThread(): 返回代码正在被哪个线程调用的信息
  • isAlive(): 判断当前线程是否处于活动状态,活动状态就是线程已经启动且尚未终止,线程处于正在运行或准备开始运行的状态就认为是”存活”的
  • sleep(): 指定毫秒数内,让‘当前’正在执行的线程休眠(暂停执行)
  • getId(): 获得线程的唯一标识。

停止线程

  • interrupt(): 仅仅是在当前线程打了一个中断的标记,并不是真正的停止线程。

判断线程是否停止状态:

1
2
this.interrupt(); //测试当前线程是否已经中断,线程的中断状态由该方法清楚,当前线程是指运行this.interrupt()方法的线程
this.isInterrupted(); //测试线程是否已经中断
  • 异常法(抛出异常来终止线程的运行)
  • 如果沉睡中停止线程,会发生异常
  • 暴力停止stop()废弃
  • return停止线程
  • 变量控制,跳出循环

线程的优先级

在操作系统中,线程可以划分优先级,优先级较高的线程得到cpu的资源较多,也就是cpu优先执行优先级较高的线程对象中的任务。
设置线程的优先级有助于帮“线程规划器”确定在下一次选择哪一个线程来优先执行。
设置线程的优先级使用setPriority()方法。
JDK使用3个常量来预置定义优先级的值,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;

/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;

/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
  • 线程的优先级具有继承性:线程A启动线程B,A与B具有相同的优先级。
  • 优先级具有规则性:大部分高优先级的线程比低优先级线程先执行,并不是一定就会比低优先级的先执行完。

守护线程

守护线程是一种特殊的线程,他的特性有“陪伴”的含义,当进程不存在非守护线程了,则守护线程自动销毁。典型的守护线程就是垃圾回收线程,当进程中没有非守护线程了,那么垃圾回收线程也就没有存在的必要了,自动销毁。

“守护线程”:任何一个守护线程都是整个JVM中所有非守护线程的“保姆”,只要当前JVM实例中存在任何一个非守护线程没有结束,守护线程就在工作,只有当最后一个非守护线程结束时,守护线程才会随着JVM一同结束工作。

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :