学习线程之前需要了解程序、进程、线程的区别
程序
程序是一组为完成一些特殊功能的计算机指令的集合。
进程
进程是正在运行中的程序,是系统进行资源分配和调用的独立单位,每个继承都有它自己的内存空间和系统资源。
线程
在一个进程中的内部可以执行多个任务,而这每一个任务可以看作一个线程。线程是程序中控制流,是程序使用CPU的基本单位
多线程的意义
多线程的作用不是提高执行速度,而是提高应用程序、CPU的使用率
在Java中多线程的使用
创建一个线程类的两种方式
很多人说Java创建线程有三种方式,当根据jdk1.8API来看,只有两种。可能是官方只认两种,也有可能是还没更新官方文档,以下写出三种方式:
- 继承Tread类并重写run()方法
public class ThreadTest01 extends Thread{
// public ThreadTest01(String name) {
// super(name);
// }
@Override
public void run() {
// 一般被线程执行的代码一定比较耗时
for (int i = 0; i < 10; i++) {
String name = super.getName();
System.out.println(name + i);
}
}
}
package com.MultiThreading;
/**
* start()和run()的区别
* start()方法首先启动线程,然后由jvm区调用该线程的run方法
* run()仅仅是封装线程执行的代码,直接调用相当于普通方法
*/
public class Test01 {
public static void main(String[] args) {
// 创建线程对象
ThreadTest01 test01 = new ThreadTest01();
ThreadTest01 test02 = new ThreadTest01();
// 直接调用run方法,相当于调用普通方法,所以看到的是单线程的效果
// test01.run();
// test01.run();
// IllegalThreadStateException:非法线程状态异常,相当于一个线程启动两次
// test01.start();
// test01.start();
// 启动线程
test01.start();
test01.setName("线程一");
test02.start();
test02.setName("线程二");
// 返回当前正在执行线程对象
Thread.currentThread().setName("主线程");
System.out.println(Thread.currentThread().getName());
}
}
/**
* start()和run()的区别
* start()方法首先启动线程,然后由jvm区调用该线程的run方法
* run()仅仅是封装线程执行的代码,直接调用相当于普通方法
*/
public class Test01 {
public static void main(String[] args) {
// 创建线程对象
ThreadTest01 test01 = new ThreadTest01();
ThreadTest01 test02 = new ThreadTest01();
// 直接调用run方法,相当于调用普通方法,所以看到的是单线程的效果
// test01.run();
// test01.run();
// IllegalThreadStateException:非法线程状态异常,相当于一个线程启动两次
// test01.start();
// test01.start();
// 启动线程
test01.start();
test01.setName("线程一");
test02.start();
test02.setName("线程二");
// 返回当前正在执行线程对象
Thread.currentThread().setName("主线程");
System.out.println(Thread.currentThread().getName());
}
}
- 实现Runnable接口并实现run()方法
public class RunnableTest03 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(Thread.currentThread().getName() + "\t" + i);
}
}
}
public class Test03 {
public static void main(String[] args) {
RunnableTest03 runnableTest03 = new RunnableTest03();
Thread thread = new Thread(runnableTest03);
thread.start();
}
}
- 实现Callable接口并实现call()方法
import java.util.concurrent.Callable;
public class CallableDemo implements Callable<Object> {
@Override
public Object call() throws Exception {
int i = 1111;
return i;
}
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CallableDemo callableDemo = new CallableDemo();
FutureTask futureTask = new FutureTask(callableDemo);
Thread thread = new Thread(futureTask);
thread.start();
Object o = futureTask.get();
System.out.println(o);
}
}
上述三种方式都可以创建一个线程类用来达到多线程的目的。
多线程常用方法
- 线程对象名.
start()
:启动线程 - 线程对象名.
setName()
:设置线程名 - 线程对象名.
getName()
:获取线程名 -
Tread.currentThread()
:返回当前正在执行的线程对象 - 线程对象名.
setPriority(int newPriority)
:设置线程优先级;默认优先级为5,最高优先级为10,最低优先级为1。注意,优先级高不代表一定会让它最先获得CPU资源,只能说它最先获取CPU资源的概率相较于优先级低的线程会大一点。设置优先级要在启动线程前设置,否则无效。 - 线程休眠
Thread.sleep(millis)
:单位为毫秒值(1s = 1000ms),设置线程睡眠时间。eg:Thread.sleep(1000)
- 线程加入:等待线程终止,才继续执行下一个线程(在启动线程之后调用)
线程对象名.join()
。 - 线程让步\线程礼让:暂停当前正在执行的线程对象(即放弃当前拥有的CPU资源),并执行其他线程。并不能保证一个线程执行一次,
Thread.yield()
,在线程体中执行 -
setDaemon(boolean on)
:将指定线程标记为守护线程或用户线程。当程序中运行的线程都为守护线程时,Java虚拟机退出。
10.中断线程:stop()
:让线程停止(已过时)interrupt()
:中断线程,把线程的状态转为终止状态,并抛出InterruptedException
线程组
把多个线程组合到一起,可以对多个线程分类管理,Java允许程序直接对线程控制
默认属于main线程组
更改默认线程组
- 创建一个线程组
- 创建其他线程时,把其他线程的组指定为创建的线程组
ThreadGroup tg = new ThreadGroup();
Thread t = new Thread(tg, new RunnableImpl());