程序、进程、线程
- 程序(program):静态代码
- 进程(process):程序的一次执行过程,或是一个正在运行中的程序
- 线程(thread):进程可以进一步细化为线程,是一个程序内部的一条执行路径
创建线程的4种方式
继承Thread类
public class ThreadTest {
public static void main(String[] args) {
new EvenPrinter().start();
new EvenPrinter().start();
}
}
/**
* 打印100以内的偶数
*/
class EvenPrinter extends Thread {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
实现Runnable接口
public class ThreadTest {
public static void main(String[] args) {
OddPrinter oddPrinter = new OddPrinter();
new Thread(oddPrinter).start();
new Thread(oddPrinter).start();
new Thread(oddPrinter).start();
}
}
/**
* 打印100以内的奇数
*/
class OddPrinter implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
实现Callable接口
与实现Runnable接口相比,实现Callable这种方式:
- 可以接收返回值
- 支持泛型
- 可抛出异常
public class ThreadTest {
public static void main(String[] args) {
NumberPrinter numberPrinter = new NumberPrinter();
FutureTask<Integer> task = new FutureTask<>(numberPrinter);
new Thread(task).start();
Integer sum = null;
try {
sum = task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("sum=" + sum);
}
}
/**
* 打印100以内的数字,并返回其和
*/
class NumberPrinter implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
sum += i;
}
return sum;
}
}
使用线程池
public class ThreadTest {
public static void main(String[] args) {
// 创建一个包含10个线程的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
// void execute(Runnable command)
service.execute(new OddPrinter());
service.execute(new EvenPrinter());
// <T> Future<T> submit(Callable<T> task)
Future<Integer> future = service.submit(new NumberPrinter());
Integer sum = 0;
try {
sum = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("sum=" + sum);
// 关闭线程池
service.shutdown();
}
}
/**
* 打印100以内的数字,并返回其和
*/
class NumberPrinter implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
sum += i;
}
return sum;
}
}
/**
* 打印100以内的奇数
*/
class OddPrinter implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
/**
* 打印100以内的偶数
*/
class EvenPrinter extends Thread {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
Thread类常用方法
- void start():启动线程,执行run()方法
- void run():线程在被调度时执行的操作
- String getName()
- void setName(String name)
- static Thread currentThread():返回当前线程
- static void yeid():线程让步,把执行机会让给其他线程
- void join():在线程a中调用线程b的join()方法,等线程b执行完毕后,继续执行线程a
- static void sleep(long millis):让当前线程休眠指定的毫秒数
- boolean isAlive():线程是否存活
public class ThreadTest {
public static void main(String[] args) {
OddPrinter oddPrinter = new OddPrinter();
Thread t1 = new Thread(oddPrinter);
// 设置线程名称
t1.setName("线程t1");
// 启动线程t1
t1.start();
// 等待线程t1执行完毕后,再继续执行后面的代码
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 线程的状态(生命周期)
System.out.println("t1.getState():" + t1.getState());
// 线程是否存活
System.out.println("t1.isAlive():" + t1.isAlive());
}
}
/**
* 打印100以内的奇数
*/
class OddPrinter implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
if (i % 2 != 0) {
// 让当前线程休眠100毫秒
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
线程的生命周期
线程同步
使用synchronized代码块解决Runnable接口实现类的线程安全问题
public class TicketWindowTest {
public static void main(String[] args) {
TicketWindow ticketWindow = new TicketWindow();
new Thread(ticketWindow, "窗口1").start();
new Thread(ticketWindow, "窗口2").start();
new Thread(ticketWindow, "窗口3").start();
}
}
/**
* 售票窗口
*/
class TicketWindow implements Runnable {
// 总共100张票
private int ticket = 100;
@Override
public void run() {
while (true) {
// 使用this作为同步监视器(锁)
synchronized (this) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
}
}
使用synchronized代码块解决Thread子类的线程安全问题
public class TicketWindowTest {
public static void main(String[] args) {
new TicketWindow().start();
new TicketWindow().start();
new TicketWindow().start();
}
}
/**
* 售票窗口
*/
class TicketWindow extends Thread {
// 总共100张票
private static int ticket = 100;
@Override
public void run() {
while (true) {
// 使用TicketWindow.class作为同步监视器(锁)
synchronized (TicketWindow.class) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
} else {
break;
}
}
}
}
}
使用synchronized方法解决Runnable接口实现类的线程安全问题
public class TicketWindowTest {
public static void main(String[] args) {
TicketWindow ticketWindow = new TicketWindow();
new Thread(ticketWindow, "窗口1").start();
new Thread(ticketWindow, "窗口2").start();
new Thread(ticketWindow, "窗口3").start();
}
}
/**
* 售票窗口
*/
class TicketWindow implements Runnable {
// 总共100张票
private int ticket = 100;
@Override
public void run() {
while (ticket > 0) {
sale();
}
}
/**
* sale方法不是静态的,将使用this作为同步监视器
*/
private synchronized void sale() {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
}
}
使用synchronized方法解决Thread子类的线程安全问题
public class TicketWindowTest {
public static void main(String[] args) {
new TicketWindow().start();
new TicketWindow().start();
new TicketWindow().start();
}
}
/**
* 售票窗口
*/
class TicketWindow extends Thread {
// 总共100张票
private static int ticket = 100;
@Override
public void run() {
while (ticket > 0) {
sale();
}
}
/**
* sale方法是静态的,将使用TicketWindow.class作为同步监视器
*/
private static synchronized void sale() {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
}
}
使用Lock接口手动开关锁
public class TicketWindowTest {
public static void main(String[] args) {
TicketWindow ticketWindow = new TicketWindow();
new Thread(ticketWindow, "窗口1").start();
new Thread(ticketWindow, "窗口2").start();
new Thread(ticketWindow, "窗口3").start();
}
}
/**
* 售票窗口
*/
class TicketWindow implements Runnable {
// 总共100张票
private int ticket = 100;
// 同步监视器
private ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
while (ticket > 0) {
lock.lock();
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + ticket--);
}
lock.unlock();
}
}
}
线程通信
三个方法:
- wait(): 令当前线程挂起并放弃CPU、同步资源并等待,使别的线程可访问并修改共享资源
- notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待
- notifyAll():唤醒正在排队等待资源的所有线程结束等待
注意点:
- 以上三个方法声明在Object类中
- 以上三个方法只能在在synchronized方法或synchronized代码块中才能使用
public class CommTest {
public static void main(String[] args) {
// 两个线程将交替打印
NumberPrinter numberPrinter = new NumberPrinter();
new Thread(numberPrinter).start();
new Thread(numberPrinter).start();
}
}
/**
* 打印1~100
*/
class NumberPrinter implements Runnable {
private int i = 1;
@Override
public void run() {
while (true) {
synchronized (this) {
if (i <= 100) {
// 唤醒一个线程
notify();
System.out.println(Thread.currentThread().getName() + ":" + i++);
// 休眠当前线程
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// 唤醒所有线程,否则程序无法自动退出
notifyAll();
break;
}
}
}
}
}