目录
[1. 继承Thread类](#1. 继承Thread类)
[2. 实现Runnable接口](#2. 实现Runnable接口)
[5.线程池 ExcuterService](#5.线程池 ExcuterService)
线程
一个进程有多个线程(进程是一个独立的工作任务和单元),线程由JVM(java虚拟机)控制。
协程:一个由用户控制的轻量级的线程。
如下面的代码所示,u1.run()属于方法调用,启动的是主线程main。u1.start()启动的是子线程,Thread-随机数。



线程的创建方式
1. 继承Thread类
java
package com.demo2;
//Thread-整数,这就是子线程的名字
public class UserThread extends Thread{
public void run()
{
System.out.println(Thread.currentThread().getName()+",run");
}
}
java
package com.demo2;
public class Test {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+",main函数");
UserThread u1 = new UserThread();
u1.start();
}
}
运行结果:

**注意:**一个线程启动以后,这个线程就不能再次启动了,这个线程已死亡。如果再次启动,这个线程会抛出线程状态异常。

2. 实现Runnable接口
Runnable接口是Thread类的父类,所以对于实现Runnable和继承Thread类来创建线程,实现Runnable比继承Thread更好,可以更好的扩展。
java
package com.demo3;
/**
* Runnable接口是Thread类的父类
*/
public class UserRunnable implements Runnable{
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+",run");
}
}
java
package com.demo3;
public class Test {
public static void main(String[] args) {
UserRunnable ur = new UserRunnable();
//把这个实现了Runnable接口的对象,构建一个线程对象
Thread r1 = new Thread(ur);
r1.start();
}
}
运行结果:

3.继承TimerTask,定时线程
java
package com.demo4;
import java.util.Date;
import java.util.TimerTask;
//定时线程
public class UserTask extends TimerTask {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+", run"+new Date());
}
}
java
package com.demo4;
import java.util.Timer;
public class Test {
public static void main(String[] args) {
// 定时线程的启动有特殊的方法
UserTask ut = new UserTask();
// 继承TimerTask不用这个方法,它是一个定时线程
// Thread t = new Thread(ut);
// t.start();
// 建立一个定时器对象
Timer t = new Timer();
// 安排定时任务执行
t.schedule(ut,1000,4000);
}
}
t.schedule(ut, 1000, 4000)
这三个参数的意思是:
ut
- 要执行的任务(必须是TimerTask
的子类)1000
- 首次执行的延迟时间(毫秒) = 1秒后开始第一次执行4000
- 后续执行的间隔时间(毫秒) = 之后每4秒执行一次
运行结果:

4.带有返回值的线程,Callable
下面的代码演示了如何使用 Callable
和 Future
接口来实现有返回值的多线程任务 。与普通的Runnable
不同,Callable
可以返回执行结果和抛出异常。
执行流程:
- 创建线程池 →
Executors.newSingleThreadExecutor()
- 创建任务 →
new UserCall()
- 提交任务 →
es.submit(uc)
返回Future
对象 - 获取结果 →
result.get()
阻塞等待任务完成 - 关闭线程池 →
es.shutdown()
java
package com.demo7;
import java.util.concurrent.Callable;
public class UserCall implements Callable<Integer>{
// Callable的call方法可以有返回值和抛出异常
public Integer call() throws Exception {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName()+",call方法");
return 10;
}
}
java
package com.demo7;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test {
public static void main(String[] args) {
// 创建单线程的线程池
ExecutorService es = Executors.newSingleThreadExecutor();
// 创建Callable任务实例
UserCall uc = new UserCall();
// 提交任务到线程池,返回Future对象
Future<Integer> result = es.submit(uc);
try {
// 获取任务执行结果(会阻塞直到任务完成)
System.out.println("返回值:"+result.get());
// 关闭线程池
es.shutdown();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:

5.线程池 ExcuterService
下面的代码演示了如何使用 Java线程池 来执行一个实现了 Runnable
接口的任务。它创建了一个单线程的线程池,然后在这个线程中执行循环打印任务。
java
package com.demo8;
public class UserRun1 implements Runnable{
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<5;i++)
{
System.out.println(Thread.currentThread().getName()+","+i);
}
}
}
java
package com.demo8;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
// 创建单线程的线程池
ExecutorService es = Executors.newSingleThreadExecutor();
// 提交Runnable任务到线程池执行
es.execute(new UserRun1());
// 关闭线程池(不再接受新任务)
es.shutdown();
}
}
Executors.newSingleThreadExecutor():
- 创建只有一个线程的线程池
- 任务会按提交顺序依次执行
- 线程会一直存在,可重复使用
execute()
vs submit():
java
// execute() - 用于Runnable,无返回值
es.execute(runnableTask);
// submit() - 可用于Runnable和Callable,返回Future对象
Future<?> future = es.submit(runnableTask);
运行结果:

线程的生命周期
- 创建线程对象
2.线程进入可运行状态 ,可以运行,JVM来调度执行
-
进入到运行状态
-
对线程的调度(沉睡,让步,合并,线程同步机制,线程通信机制,JUC线程机制)
5.死亡

对线程的调度
沉睡-Thread.sleep()
让当前正在运行的线程睡眠,当睡眠时间到,线程再次进入可运行状态,再次执行还是由JVM调度。
java
package com.thread1;
public class UserThread extends Thread {
public void run()
{
System.out.println(Thread.currentThread().getName()+",线程执行run方法开始");
try {
//Thread表示当前线程
//让当前正在运行的线程睡眠
//睡眠时间到,线程再次进入可运行状态,再次执行还是由JVM调度
Thread.sleep(6*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",线程执行run方法之后");
}
}
java
package com.thread1;
public class Test {
public static void main(String[] args) {
for(int i=0;i<5;i++)
{
UserThread u1 = new UserThread();
u1.start();
}
}
}
运行结果:

让步-Thread.yeild()
当前的线程进行让步,即让出执行权,可能选择让或不让。
java
package com.thread2;
public class UserThread extends Thread{
public void run()
{
System.out.println("A");
//让步,让出执行权,可能选择让或不让
Thread.yield();
System.out.println("B");
//AABB或ABAB
}
}
java
package com.thread2;;
public class Test {
public static void main(String[] args) {
UserThread u1 = new UserThread();
UserThread u2 = new UserThread();
u1.start();
u2.start();
}
}
运行结果:


合并-Thread.join()
合并线程去执行。
java
package com.thread3;
public class UserThread extends Thread{
int sum =0;
public void run()
{
for(int i=0;i<=100;i++)
{
sum += i;
}
}
public int getSum()
{
return this.sum;
}
}
java
package com.thread3;
public class Test {
public static void main(String[] args) {
UserThread u1 = new UserThread();
u1.start();
try {
//主线程和子线程的生命周期是隔离的
//合并到主线程执行
u1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("得到子线程的值为:"+u1.getSum());
}
}
运行结果:

线程的优先级
线程的优先级取值1..10,但是不能够绝对保证优先级高的线程最先启动,只是在一段时候内,最先运行的概率高一点。
java
package com.demo10;
public class UserThread extends Thread{
public void run()
{
System.out.println(Thread.currentThread().getName()+",run...");
}
}
java
package com.demo10;
public class Test {
public static void main(String[] args) {
UserThread u1 = new UserThread();
UserThread u2 = new UserThread();
UserThread u3 = new UserThread();
//线程的优先级取值1..10,但是不能够绝对保证优先级高的线程最先启动
//在一段时候内,最先运行的概率高一点
u3.setPriority(Thread.MAX_PRIORITY);
u1.setPriority(Thread.MIN_PRIORITY);
u1.start();
u2.start();
u3.start();
}
}
运行结果:
