线程生命周期
线程方法
静态方法
- currentThread 获取当前线程
实例方法
- getName() 获取线程名字
- setName() 设置线程名字
- yield() 放弃CPU执行权,进入就绪状态
线程创建方式
有四种方式创建线程
- 继承Thread的子类,每个线程的任务都不相同
- Runnable接口的实现类,多个线程可以共享同一任务对象,任务数据可共享
- Callable接口的实现类,多个线程可以共享同一任务对象,任务数据可共享,且可获取线程返回值
- 通过线程池创建线程,多个线程可以共享同一任务对象,任务数据可共享,且可获取线程返回值,自动创建线程
继承Thread的子类
package com.thread;
public class ThreadDemo {
public static void main(String[] args) {
SubThread thread = new SubThread();
thread.start();
}
}
class SubThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
}
}
}
Runnable接口的实现类
package com.thread;
public class RunnableDemo {
public static void main(String[] args) {
CountTask1 thread = new CountTask1();
Thread containerThread = new Thread(thread, "计数线程");
containerThread.start();
}
}
class CountTask1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
Callable实现类
package com.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CountTask countTask = new CountTask();
FutureTask<Boolean> futureTask = new FutureTask<Boolean>(countTask);
Thread thread = new Thread(futureTask, "计数线程");
thread.start();
while (futureTask.get()) {
System.out.println("计数线程执行完毕");
break;
}
}
}
class CountTask implements Callable {
@Override
public Boolean call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
return true;
}
}
线程池
package com.thread;
import java.util.concurrent.*;
public class ThreadPoolDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CountTask2 countTask = new CountTask2();
ExecutorService executorService = Executors.newFixedThreadPool(5);
Future futureTask = executorService.submit(countTask);
while ((Boolean)futureTask.get()) {
System.out.println("计数线程执行完毕");
break;
}
}
}
class CountTask2 implements Callable {
@Override
public Boolean call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
return true;
}
}
线程安全
多个线程访问并操作共享数据时会存在线程安全问题 解决方法:
- 同步锁synchronized
- 可重入锁ReentrantLock
synchronized
同步代码块
- 对代码块加同步锁
- 多个线程只有共享一个同步锁,才不会发生抢占
- 同步锁可以是任意一个对象
package com.threadsafe;
public class SynchronizedBlockDemo {
public static void main(String[] args) {
BuyTicketsTask task = new BuyTicketsTask();
Thread thread1 = new Thread(task, "甲");
Thread thread2 = new Thread(task, "乙");
thread1.start();
thread2.start();
}
}
class BuyTicketsTask implements Runnable {
private int tickets = 100;
@Override
public void run() {
while (true) {
synchronized (this) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName()+ "购得第" + tickets + "张票");
tickets--;
System.out.println("当前余票:" + tickets);
Thread.currentThread().yield();
} else {
break;
}
}
}
}
}
同步方法
- 对方法加同步锁
- 如果是非静态方法,同步锁为当前对象this
- 如果是静态方法,同步锁为当前类BuyTicketsTask1.class
package com.threadsafe;
public class SynchronizedMethodDemo {
public static void main(String[] args) {
BuyTicketsTask1 task = new BuyTicketsTask1();
Thread thread1 = new Thread(task, "甲");
Thread thread2 = new Thread(task, "乙");
thread1.start();
thread2.start();
}
}
class BuyTicketsTask1 implements Runnable {
private int tickets = 100;
public synchronized void buyTickets () {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName()+ "购得第" + tickets + "张票");
tickets--;
System.out.println("当前余票:" + tickets);
Thread.currentThread().yield();
}
}
@Override
public void run() {
while (tickets > 0) {
buyTickets();
}
}
}
可重入锁ReentrantLock
- 可以随时锁,随时解锁
package com.threadsafe;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockDemo {
public static void main(String[] args) {
BuyTicketsTask2 task = new BuyTicketsTask2();
Thread thread1 = new Thread(task, "甲");
Thread thread2 = new Thread(task, "乙");
thread1.start();
thread2.start();
}
}
class BuyTicketsTask2 implements Runnable {
private int tickets = 100;
ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
lock.lock();
if (tickets > 0) {
System.out.println(Thread.currentThread().getName()+ "购得第" + tickets + "张票");
tickets--;
System.out.println("当前余票:" + tickets);
Thread.currentThread().yield();
} else {
break;
}
} finally {
lock.unlock();
}
}
}
}