一、继承Thread类
package MultiPluThread.createThread;
/**
* Created by IntelliJ IDEA.
*
* @Author : yuankai
* @create 2024/7/11 21:22
*/
public class MyThread extends Thread{
// 这个线程内的变量就是共享变量,这里不同的线程售出了相同的票
private int ticket = 15;
@Override
public void run() {
while(ticket >0) {
System.out.println(this.getName() + "售出第" + ticket + "张票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket--;
if(ticket < 0) {
System.out.println("售票结束");
}
}
}
}
二、实现Runnable接口
package MultiPluThread.createThread;
public class MyRunnable implements Runnable{
private int ticket = 15;
@Override
public void run() {
while(ticket >0) {
System.out.println(Thread.currentThread().getName()+ "售出第" + ticket + "张票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket--;
if(ticket < 0) {
System.out.println("售票结束");
}
}
}
}
三、实现Callable接口
package MultiPluThread.createThread;
import java.util.concurrent.Callable;
/**
* Created by IntelliJ IDEA.
*
* @Author : yuankai
* @create 2024/7/11 21:47
*/
public class MyCallable implements Callable<Integer> {
// 这里的返回值与Callable接口的泛型对应
@Override
public Integer call() throws Exception {
int result = 0;
for(int i = 0; i < 15; i++) {
result += i;
}
return result;
}
}
四、Test测试类
package MultiPluThread.createThread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
/**
* Created by IntelliJ IDEA.
*
* @Author : yuankai
* @create 2024/7/11 21:23
*/
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 方式一
new MyThread().start();
new MyThread().start();
// 方式二
MyRunnable mr = new MyRunnable();
new Thread(mr).start();
new Thread(mr).start();
// 方式三
MyCallable callable = new MyCallable();
FutureTask<Integer> result1 = new FutureTask<>(callable);
FutureTask<Integer> result2 = new FutureTask<>(callable);
Thread thread1 = new Thread(result1);
Thread thread2 = new Thread(result2);
thread1.start();
thread2.start();
Integer intResult1 = result1.get();
Integer intResult2 = result2.get();
System.out.println(intResult1 + "--" +intResult2);
}
}
五、线程安全
1.任意运行一种方式,我们可以发现当多个线程同时处理变量ticket的时候,会出现同时出售的情况,为什么解决这个问题,我们使用了synchronized关键字,来让ticket变量只能同时被一个线程所处理

六、synchronized的使用方式
1.修饰this变量,即修饰当前对象,只对同一个runnable变量生效,多个Runnable不起作用。(如果是修饰Object,和this类似,则只有当一个线程结束对Object的访问时,才会允许其他线程访问)
①Runnable接口实现类
package MultiPluThread.createThread;
public class MyRunnable implements Runnable{
private int ticket = 15;
@Override
public void run() {
synchronized (this) {
while (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "售出第" + ticket + "张票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket--;
if (ticket < 0) {
System.out.println("售票结束");
}
}
}
}
}
②Test测试类
package MultiPluThread.createThread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
/**
* Created by IntelliJ IDEA.
*
* @Author : yuankai
* @create 2024/7/11 21:23
*/
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 多线程不是指多次执行run方法,而是指我们可以创建多个线程来"同时"执行run里面的方法
// 方式一
// new MyThread().start();
// new MyThread().start();
// 方式二,多个MyRunnable,锁不会生效
MyRunnable mr = new MyRunnable();
MyRunnable mr2 = new MyRunnable();
new Thread(mr).start();
new Thread(mr2).start();
// 方式三,callable能接受该线程的run方法的返回值和异常
// MyCallable callable = new MyCallable();
// FutureTask<Integer> result1 = new FutureTask<>(callable);
// FutureTask<Integer> result2 = new FutureTask<>(callable);
// Thread thread1 = new Thread(result1);
// Thread thread2 = new Thread(result2);
// thread1.start();
// thread2.start();
// Integer intResult1 = result1.get();
// Integer intResult2 = result2.get();
// System.out.println(intResult1 + "--" +intResult2);
}
}
③图解

2.修饰方法或代码块
①锁定对象是函数对象,当这个函数或代码块被线程A使用时,线程B访问该函数或代码块将被堵塞,直到线程A使用完毕
package MultiPluThread.createThread;
public class MyRunnable implements Runnable{
private int ticket = 15;
private Object lock;
@Override
public synchronized void run() {
while (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "售出第" + ticket + "张票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket--;
if (ticket < 0) {
System.out.println("售票结束");
}
}
}
}
3.修饰静态方法和Class
①静态方法代码
package MultiPluThread.createThread;
public class MyRunnable implements Runnable{
private static int ticket = 15;
private Object lock;
@Override
public synchronized void run() {
method();
}
public synchronized static void method() {
while (ticket > 0) {
System.out.println(Thread.currentThread().getName() + "售出第" + ticket + "张票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
ticket--;
if (ticket < 0) {
System.out.println("售票结束");
}
}
}
}
②Test测试类
package MultiPluThread.createThread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
/**
* Created by IntelliJ IDEA.
*
* @Author : yuankai
* @create 2024/7/11 21:23
*/
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 多线程不是指多次执行run方法,而是指我们可以创建多个线程来"同时"执行run里面的方法
// 方式一
// new MyThread().start();
// new MyThread().start();
// 方式二,多个MyRunnable,但静态方法是类级别的,因此也会生效
MyRunnable mr = new MyRunnable();
MyRunnable mr2 = new MyRunnable();
new Thread(mr).start();
new Thread(mr2).start();
// 方式三,callable能接受该线程的run方法的返回值和异常
// MyCallable callable = new MyCallable();
// FutureTask<Integer> result1 = new FutureTask<>(callable);
// FutureTask<Integer> result2 = new FutureTask<>(callable);
// Thread thread1 = new Thread(result1);
// Thread thread2 = new Thread(result2);
// thread1.start();
// thread2.start();
// Integer intResult1 = result1.get();
// Integer intResult2 = result2.get();
// System.out.println(intResult1 + "--" +intResult2);
}
}
③测试结果,当Thread0执行时,尽管他们是不同的Runnable实例,但是属于同一个类,因此线程B依然会阻塞。Class同理,对于一个类只有一个class文件,因此对于不同的Runnable实例,线程B依然会被锁所阻塞

**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。