目录
一、线程、进程和内存
线程和进程
进程是系统进行资源分配和调度的基本单位,一个进程中至少有一个线程,进程中的多个线程共享进程的资源。线程是进程中的一个实体,线程是不会独立存在的! 所以说,没有进程就就没有线程。
对于CPU资源比较特殊,线程才是CPU分配的基本单位。
main函数启动 ——>JVM进程 ——>main函数线程称为主线程
内存与线程
内存与线程的关系,主要是指JVM内存模型与线程之间的关系,它也是线程安全问题的主要诱因。
//共享内存引发线程安全问题
二、Java执行线程任务的三种方式
1、直接继承Thread
Java不支持多继承,如果继承了Thread类,那么子类不能再继承其他类,但是使用简单,直接new出来就可以使用,对象还可以直接调用Thread类的相关方法;
/**
* @author swadian
* @date 2022/2/15
* @Version 1.0
*/
public class CreateThreadExtendsThread extends Thread {
private Account account;
public static void main(String[] args) {
//创建账号
Account account = new Account("909090", "swadian", true);
//创建线程1
CreateThreadExtendsThread thread1 = new CreateThreadExtendsThread("thread1");
thread1.setAccount(account);
System.out.println("start前thread1状态:" + thread1.getState());
//线程执行
thread1.start();
try {
//主线程睡眠->保证线程执行完
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("start后thread1状态:" + thread1.getState());
//创建线程2
CreateThreadExtendsThread thread2 = new CreateThreadExtendsThread("thread2", account);
thread2.start();
}
public CreateThreadExtendsThread() {
}
public CreateThreadExtendsThread(String name) {
//继承父类的有参构造
super(name);
}
public CreateThreadExtendsThread(String name, Account account) {
super(name);
this.account = account;
}
public void setAccount(Account account) {
this.account = account;
}
//线程执行内容
public void run() {
System.out.println(Thread.currentThread().getName() + " Account's information : " + this.account + "," + this.getState());
}
}
执行结果
2、实现Runnable接口
实现了Runnable接口还可以继承其他类。但是必须借助Thread类来执行,实现类作为一个参数进行传入
/**
* @author swadian
* @date 2022/2/15
* @Version 1.0
* 实现而非继承
*/
public class CreateThreadImplementsRunnable implements Runnable {
private Account account;
public static void main(String[] args) {
Account account = new Account("919191", "swadian", true);
CreateThreadImplementsRunnable thread1 = new CreateThreadImplementsRunnable();
thread1.setAccount(account);
new Thread(thread1, "thread1").start();//借助Thread执行线程
CreateThreadImplementsRunnable thread2 = new CreateThreadImplementsRunnable(account);
new Thread(thread2, "thread2").start();
//内部类,接口的特有方式
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 内部类:new Runnable ...");
}
}, "thread3").start();
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Account's information : " + this.account);
}
public CreateThreadImplementsRunnable() {
}
// 传参可以使用构造函数也可以使用set方法
public CreateThreadImplementsRunnable(Account account) {
this.account = account;
}
public void setAccount(Account account) {
this.account = account;
}
}
执行结果
3、实现Callable接口
前两种方式都没办法拿到任务的返回结果,但是Callable方式可以。不过必须借助FutureTask来封装返回结果,借助Thread类来启动线程。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* @author swadian
* @date 2022/2/15
* @Version 1.0
* @describetion 返回结果为Account对象
*/
public class CreateThreadImplementsCallable implements Callable<Account> {
private Account account;
public static void main(String[] args) {
Account account = new Account("929292", "swadian", true);
CreateThreadImplementsCallable call = new CreateThreadImplementsCallable(account);
FutureTask<Account> ft = new FutureTask<Account>(call);//借助FutureTask来封装返回结果
new Thread(ft, "thread-call").start();//借助Thread类来启动线程
try {
Account result = ft.get();//返回结果为Account对象
System.out.println(Thread.currentThread().getName() + "获取返回内容: " + result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Override//具体执行内容
public Account call() throws Exception {
System.out.println(Thread.currentThread().getName() + " Account's information : " + this.account);
this.account.setValid(false);
Thread.sleep(3000);
return this.account;
}
public CreateThreadImplementsCallable() {
}
public CreateThreadImplementsCallable(Account account) {
this.account = account;
}
public void setAccount(Account account) {
this.account = account;
}
}
执行结果
附:Account类
public class Account {
private String accountNo;
private String accountName;
private boolean valid;
public Account() {
}
public Account(String accountNo, String accountName, boolean valid) {
this.accountNo = accountNo;
this.accountName = accountName;
this.valid = valid;
}
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
@Override
public String toString() {
return "Account{" +
"accountNo='" + accountNo + '\'' +
", accountName='" + accountName + '\'' +
", valid=" + valid +
'}';
}
}