线程的创建
1、创建一个Thread类,或者一个Thread子类的对象。
Thread类
Thread是一个线程类,位于java.lang包下。
Thread类的常用方法
通过继承Thread类的方式创建线程类,重写run()方法。
class MyThread extends Thread{
@Override
public void run() {
System.out.println("一个线程运行");
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyThread mt = new MyThread();
// 启动线程
mt.start();
}
}
2、创建一个实现Runnable接口的类的对象。
- 只有一个方法run();
- Runnable是java中用以实现线程的接口。
- 任何实现线程功能的类都必须实现该接口。
为什么要实现Runnable接口?
1、java不支持多继承。
2、不打算重写Thread类的其他方法。
创建步骤:
- 声明实现Runnable接口的类。
- 在实现类内实现run()方法。
- 创建实现类的对象。
- 通过实现类的对象创建线程类的对象。
- 调用start()方法启动线程。
class PrintRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在运行");
}
}
public class runnable {
public static void main(String[] args) {
PrintRunnable pr = new PrintRunnable();
Thread th = new Thread(pr);
th.start();
}
}
3、实现callable接口,重写call()方法,并且可以对异常进行声明和抛出。
- 创建Callable接口的实现类,并实现call()方法,call()作为线程的执行体,具有返回值。
- 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
- 使用FutureTask对象作为Thread对的target创建并启动新线程。
- 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
- 使用start()方法来启动线程。
import java.util.concurrent.Callable;
// 实现Callable接口
public class MyThread implements Callable<String> {
@Override
public String call() throws Exception {
return "创建一个多线程";
}
}
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ThreadTest {
public static void main(String[] args) {
Callable<String> call = new MyThread();
FutureTask<String> ft = new FutureTask<>(call);
Thread t = new Thread(ft);
t.start();//启动线程
try{
System.out.println(ft.get());
}catch (Exception e){
e.printStackTrace();
}
}
}
线程的声明周期
线程的状态
新建(New)
可运行(Runnable)
正在运行(Running)
阻塞(Blocked)
终止(Dead)
sleep方法
Thread类的方法
public static void sleep(long millis)
在指定的毫秒数内让正在执行的线程休眠。
class MyThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 30; i++) {
System.out.println(Thread.currentThread().getName()
+"执行第"+(i+1)+"次!");
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
public class SleepDemo {
public static void main(String[] args) {
MyThread mt = new MyThread();
Thread t = new Thread(mt);
t.start();
Thread t1 = new Thread();
t1.start();
}
}
join方法
Thread类的方法
public final void join()
等待调用该方法的线程结束后才能执行。
public final void join(long millis)
等待该线程终止的最长时间为millis毫秒。如果millis为0则意味着要一直等下去。
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(getName()+
"正在执行"+(i+1)+"次!");
}
}
}
public class JoinDemo {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
try {
mt.join(1);
}catch (InterruptedException e){
e.printStackTrace();
}
for (int i = 0; i < 20; i++) {
System.out.println("主线程运行第"+(i+1)+"次!");
}
System.out.println("主线程运行结束!");
}
}
线程的优先级
- Java为线程类提供了10个优先级。
- 优先级可以用整数1-10表示,超过范围会抛出异常。
- 主线程默认优先级为5.
- 优先级常量:
MAX_PRIORITY:线程的最高优先级10
MIN_PRIORITY:线程的最低优先级1
NORM_PRIORITY:线程的默认优先级5 - 优先级相关方法
class MyThread extends Thread{
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println(name + "正在运行" + (i+1));
}
}
}
public class PriorityDemo {
public static void main(String[] args) {
int mainPriority = Thread.currentThread().getPriority();
System.out.println(mainPriority);//主线程优先级
MyThread mt1 = new MyThread("线程一");
MyThread mt2 = new MyThread("线程二");
mt1.setPriority(Thread.MAX_PRIORITY);
mt1.start();
mt2.start();
}
}
多线程运行问题
- 各个线程是通过竞争CPU时间而获得运行机会的。
- 各线程什么时候得到CPU,时间占用多久,是不可预测的。
- 一个正在运行的线程在什么地方被暂停是不确定的。
可以使用synchronized关键字使得线程同步。
synchronized关键字可以用在成员方法、静态方法及语句块上。
public synchronized void save(){}
public static synchronized void save(){}
synchronized(obj){}
线程间的通信
- wait() 中断方法的执行,使线程等待。
- notify() 唤醒处于等待的某一个线程,使其结束等待。
- notifyAll() 唤醒所有处于等待的线程,使他们结束等待。
一个小栗子:
public class Queue {
private int n;
boolean flag = false;
public synchronized int get(){
if(!flag){
try {
wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("消费:"+n);
flag = false;//消费完毕,容器中没有数据
notifyAll();
return n;
}
public synchronized void set(int n){
if (flag){
try {
wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("生产:"+n);
this.n = n ;
flag = true;//生产完毕,容器中已经有数据
notifyAll();
}
}
public class Producer implements Runnable {
Queue queue;
public Producer(Queue queue) {
this.queue = queue;
}
@Override
public void run() {
int i = 0;
while (true){
queue.set(i++);
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
public class Consumer implements Runnable {
Queue queue;
public Consumer(Queue queue) {
this.queue = queue;
}
@Override
public void run() {
while (true){
queue.get();
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
测试类:
public class Test {
public static void main(String[] args) {
Queue queue = new Queue();
new Thread(new Producer(queue)).start();
new Thread(new Consumer(queue)).start();
}
}