1、实现Runna接口创建线程:
测试代码:
package test.runnable;
public class MultiThreadedCalculations {
// 计算0到n的整数和
static class SumTask implements Runnable {
private int n;
public SumTask(int n) {
this.n = n;
}
@Override
public void run() {
int sum = 0;
for (int i = 0; i <= n; i++) {
sum += i;
}
System.out.println(Thread.currentThread().getName() + " 计算0到" + n + "的整数和结果为: " + sum);
}
}
// 计算0到n的阶乘
static class FactorialTask implements Runnable {
private int n;
public FactorialTask(int n) {
this.n = n;
}
@Override
public void run() {
long factorial = 1;
for (int i = 1; i <= n; i++) {
factorial *= i;
}
System.out.println(Thread.currentThread().getName() + " 计算0到" + n + "的阶乘结果为: " + factorial);
}
}
// 计算0到n的平方和
static class SquareSumTask implements Runnable {
private int n;
public SquareSumTask(int n) {
this.n = n;
}
@Override
public void run() {
int sum = 0;
for (int i = 0; i <= n; i++) {
sum += i * i;
}
System.out.println(Thread.currentThread().getName() + " 计算0到" + n + "的平方和结果为: " + sum);
}
}
public static void main(String[] args) {
// 创建线程任务
Runnable sumTask = new SumTask(100);
Runnable factorialTask = new FactorialTask(8);
Runnable squareSumTask = new SquareSumTask(12);
// 创建并启动线程
Thread sumThread = new Thread(sumTask, "整数和线程");
Thread factorialThread = new Thread(factorialTask, "阶乘线程");
Thread squareSumThread = new Thread(squareSumTask, "平方和线程");
// 启动线程
sumThread.start();
factorialThread.start();
squareSumThread.start();
}
}
2、同步代码块解决数据安全的问题:
测试代码:
package test.runnable;
//同步代码块
public class SafeCounter {
private int count = 0;
// 定义一个对象,通常可以使用`this`或者当前类的某个私有对象作为锁
// 使用一个私有的final对象
private final Object lock = new Object();
// 增加计数的方法,使用同步代码块
public void increment() {
synchronized (lock) {
count++; // 只有获得了lock锁的线程才能执行这行代码
}
}
// 获取计数的当前值
public int getCount() {
return count;
}
// 测试方法,创建多个线程来增加计数并打印最终结果
public static void main(String[] args) throws InterruptedException {
SafeCounter counter = new SafeCounter();
// 创建多个线程来增加计数
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < 1000; j++) {
counter.increment();
}
});
threads[i].start();
}
// 等待所有线程完成
for (Thread t : threads) {
t.join();
}
// 打印最终结果,计数是准确的。
System.out.println("Final count: " + counter.getCount());
}
}
3、同步方法解决数据安全的问题:
package test.runnable;
public class SafeCounterTest {
private int count = 0;
// 同步方法,确保一次只有一个线程能执行该方法
public synchronized void increment() {
count++;
}
// 获取计数的当前值
public int getCount() {
return count;
}
// 测试方法,创建多个线程增加计数并打印最终结果
public static void main(String[] args) throws InterruptedException {
SafeCounterTest counter = new SafeCounterTest();
// 创建多个线程增加计数
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
final int threadNum = i;
threads[i] = new Thread(() -> {
for (int j = 0; j < 1000; j++) {
counter.increment(); // 调用同步方法
}
// 添加打印语句观察每个线程的执行情况
System.out.println("Thread " + threadNum + " finished");
});
threads[i].start();
}
// 等待所有线程完成
for (Thread t : threads) {
t.join();
}
// 打印最终结果
System.out.println("Final count: " + counter.getCount());
}
}
4、同步方法和静态同步方法的锁对象。
package test.runnable;
//同步方法和静态同步方法的锁对象。
public class SyncMethodDemo {
// 实例变量
private int count = 0;
// 实例同步方法
public synchronized void instanceSyncMethod() {
for (int i = 0; i < 5; i++) {
count++;
try {
// 耗时操作
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println(Thread.currentThread().getName() + " 完成实例同步方法, count = " + count);
}
// 静态同步方法
public static synchronized void staticSyncMethod() {
int staticCount = 0;
for (int i = 0; i < 5; i++) {
staticCount++;
try {
// 耗时操作
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.println(Thread.currentThread().getName() + " 完成静态同步方法, staticCount = " + staticCount);
}
//实例同步方法:instanceSyncMethod 方法通过 this 锁对象进行同步.
//如果两个线程在相同的 SyncMethodDemo 实例上调用此方法,将不能同时执行该方法。
//在不同的实例上调用,可以并行执行。
//静态同步方法:staticSyncMethod 方法,通过类的 Class 对象进行同步。
//无论在哪个实例上调用此方法,所有线程都将竞争同一把锁,因此一次只能有一个线程执行该方法。
//main 方法中,创建了四个线程来演示同步方法的行为。
//两个线程调用实例同步方法,两个线程调用静态同步方法。
public static void main(String[] args) {
SyncMethodDemo instance1 = new SyncMethodDemo();
SyncMethodDemo instance2 = new SyncMethodDemo();
// 创建并启动线程,使用同步方法。
Thread t1 = new Thread(() -> instance1.instanceSyncMethod(), "Thread-1");
Thread t2 = new Thread(() -> instance2.instanceSyncMethod(), "Thread-2");
// 静态同步方法,不需要实例
Thread t3 = new Thread(SyncMethodDemo::staticSyncMethod, "Thread-3");
Thread t4 = new Thread(SyncMethodDemo::staticSyncMethod, "Thread-4");
// 启动线程
t1.start();
t2.start();
t3.start();
t4.start();
// 同步方法和静态同步方法使用的是不同的锁对象(实例的`this`和类的`Class`对象)
}
}
5、 使用ReentrantLock作为锁,解决数据安全的问题:
package test.runnable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SafeCounterWithLock {
private int count = 0;
// 使用ReentrantLock作为锁
private final Lock lock = new ReentrantLock();
// 使用Lock锁保护count的递增
public void increment() {
lock.lock(); // 获取锁
try {
count++;
} finally {
lock.unlock(); // 释放锁,无论是否发生异常
}
}
// 获取计数的当前值
public int getCount() {
return count;
}
// 创建多个线程增加计数并打印最终结果
public static void main(String[] args) throws InterruptedException {
SafeCounterWithLock counter = new SafeCounterWithLock();
// 创建多个线程增加计数
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < 1000; j++) {
counter.increment();
}
});
threads[i].start();
}
// 等待所有线程完成
for (Thread t : threads) {
t.join();
}
// 打印最终结果
System.out.println("Final count: " + counter.getCount());
}
}
6、某知识竞赛共有100道题目,有4人抢答,所有参与者均有同等的机会抢答到其中的25道题目。
测试代码1:
package test.runnable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
//抢占式线程,不带同步锁,4个参赛者并不是机会均等。
public class QuizContest {
private static final int TOTAL_QUESTIONS = 100;
private final AtomicInteger currentQuestion = new AtomicInteger(1);
public static void main(String[] args) {
QuizContest contest = new QuizContest();
ExecutorService executor = Executors.newFixedThreadPool(4);
// 创建并启动4个参赛者线程
for (int i = 1; i <= 4; i++) {
final int contestantId = i;
executor.submit(() -> {
while (true) {
int nextQuestion = contest.attemptAnswer();
if (nextQuestion == 0) {
// 所有题目都已被抢答完毕
break;
}
// 假设抢答成功,打印信息
System.out.println("参赛者 " + contestantId + " 抢答了题目 " + nextQuestion);
}
});
}
// 关闭ExecutorService,并等待所有任务完成
executor.shutdown();
try {
if (!executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
System.out.println("所有题目抢答完毕!");
}
// 尝试抢答题目,如果成功则返回题目编号,如果所有题目都已被抢答则返回0
private int attemptAnswer() {
int current = currentQuestion.get();
if (current > TOTAL_QUESTIONS) {
// 所有题目都已被抢答完毕
return 0;
}
// 尝试更新当前题目编号
if (currentQuestion.compareAndSet(current, current + 1)) {
// 抢答成功,返回题目编号
return current;
}
// 抢答失败,可能是其他线程已经抢答了这道题目
return 0;
}
}
运行结果如下:
测试代码2:
package test.runnable;
public class QuizCompetition {
private int remainingQuestions = 100;
private final Object lock = new Object();
// 同步锁实现抢答题目方法,使每个参赛者具有相等的抢答数量。
public synchronized void answerQuestion(int playerIndex) throws InterruptedException {
// 等待直到有剩余题目
while (remainingQuestions <= 0) {
lock.wait(); // 使用synchronized方法的隐式锁。
}
// 检查当前是否还有剩余题目供参与者抢答
if (remainingQuestions > 0) {
// 每个参与者都记录自己的抢答次数(在实际应用中,通过某种共享数据结构实现)
// 打印并减少剩余题目数
System.out.println("参与者 " + (playerIndex + 1) + " 抢答了题目 #" + (101 - remainingQuestions));
remainingQuestions--;
// 唤醒其他等待的线程
// lock.notifyAll(); //
Thread.sleep(10); // 假设抢答之间有微小的间隔
}
}
public static void main(String[] args) {
QuizCompetition competition = new QuizCompetition();
// 创建四个线程表示四个参与者
for (int i = 0; i < 4; i++) {
final int playerIndex = i;
new Thread(() -> {
try {
for (int j = 0; j < 25; j++) {
competition.answerQuestion(playerIndex);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
}
运行结果如下:
7、生产者消费者模式:
测试代码:
package test.runnable;
public class ProducerConsumerExample {
private static final int BUFFER_SIZE = 10;
private final int[] buffer;
private int count = 0;
private int head = 0;
private int tail = 0;
public ProducerConsumerExample(int size) {
this.buffer = new int[size];
}
// 生产者
public void produce(int item) throws InterruptedException {
synchronized (this) {
// 缓冲区满时等待
while (count == BUFFER_SIZE) {
wait();
}
// 生产产品
buffer[tail] = item;
System.out.println("Produced: " + item);
tail = (tail + 1) % BUFFER_SIZE;
count++;
// 通知消费者
notifyAll();
}
}
// 消费者
public int consume() throws InterruptedException {
synchronized (this) {
// 缓冲区空时等待
while (count == 0) {
wait();
}
// 消费产品
int item = buffer[head];
System.out.println("Consumed: " + item);
head = (head + 1) % BUFFER_SIZE;
count--;
// 通知生产者
notifyAll();
return item;
}
}
public static void main(String[] args) {
ProducerConsumerExample pc = new ProducerConsumerExample(BUFFER_SIZE);
// 生产者线程
Thread producer = new Thread(() -> {
for (int i = 0; i < 50; i++) {
try {
pc.produce(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// 消费者线程
Thread consumer = new Thread(() -> {
for (int i = 0; i < 50; i++) {
try {
pc.consume();
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
producer.start();
consumer.start();
}
}
运行结果如下:
8、线程池:
package test.runnable;
//线程池(ThreadPool)是一种基于池化技术管理线程的技术,可以减少线程创建和销毁的开销,提高系统的响应速度。
//ExecutorService接口是最核心的接口。
//使用Executors工厂类创建线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadPoolDemo {
public static void main(String[] args) {
// 创建一个固定数量为5的线程池,同时最多有5个线程执行。
ExecutorService executorService = Executors.newFixedThreadPool(5);
// 使用lambda表达式或匿名内部类定义任务
for (int i = 0; i < 10; i++) {
int taskId = i;
executorService.submit(() -> {
// 耗时任务
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 执行任务
System.out.println(Thread.currentThread().getName() + " 完成了任务 " + taskId);
});
}
// 关闭线程池,不会立即关闭线程池,而是不再接受新的任务,
// 它会等待所有已提交的任务(包括尚未开始执行的)完成后才终止。
executorService.shutdown();
try {
// 等待线程池中的任务全部完成
// 如果调用shutdownNow,方法会立即返回false,不再等待
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
// 如果超时时间到了,但任务还没执行完,可以选择取消剩余的任务
executorService.shutdownNow();
}
} catch (InterruptedException e) {
// 当前线程在等待过程中被中断
executorService.shutdownNow();
// 保留中断状态
Thread.currentThread().interrupt();
}
// 实际应用中,awaitTermination的调用可能会根据具体需求有所不同。
// 例如,在某些情况下,可能不需要等待所有任务完成,或者可能想要以不同的方式处理中断。
}
}
运行结果如下: