1.继承Thread类,覆盖定义run方法实现
class LeftThread extends Thread {
public void run() { //线程的执行线索定义在run方法中,run方法是覆盖Thread类中的方法进行定义
for (int i = 0; i < 50; i++) { // 如果需要反复执行的动作,则需要在run方法中使用循环
System.out.println("左手一个慢动作"+i);
try {
this.sleep(300);//使当前线程对象停止300毫秒,参数为long,单位为毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
优点:可以直接使用Thread类中的方法,代码简单
缺点:继承Thread类之后就不能继承其他的类
QA:是否可以直接调用run方法? 可以,但子线程不会启动
2.实现Runable接口并使用接口提供的run方法
class RightThread implements Runnable { //实现接口的方式定义线程
public void run() { //接口中定义的抽象方法
for (int i = 0; i < 50; i++){
System.out.println("右手慢动作重播"+i);
try {
Thread.currentThread().sleep(300);//使当前线程对象停止300毫秒。由于当前类并没有继承于Thread类,所以不能直接调用sleep方法,需要通过Thread.currentThread()获取运行程序的线程对象才能调用sleep方法
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//创建线程对象
//Thread t1=new Thread(new A2());
//启动线程,执行A2的run方法
//t1.start();
优点:即使自定义类已经有父类了也不受影响,因为可以实现多个接口
缺点:在run方法内部需要获取到当前线程的Thread对象后才能使用Thread中的方法
实现run方法时没有返回值,所以需要获取线程的执行结果需要自行编程实现
public class A3 implements Runnable {
private int begin,end;
private int result;
public A3(int begin,int end){
this.begin=begin;
this.end=end;
}
public void run(){
for(int i=begin;i<=end;i++){
result+=i;
}
}
public int getResult(){
return this.result;
}
}
3.实现Callable接口和Future接口的方法
class A3 implements Callable { // <>叫做泛型,可以理解为类型参数
private int begin,end;
public A3(int begin,int end){
this.begin=begin;
this.end=end;
}
@Override
public Object call() throws Exception {
int res=0;
for(int i=begin;i<=end;i++)
res+=i;
return res;
}
}
//创建并启动线程对象
//Java针对Future和Runnable接口提供了一个实现类FutureTask
//Callable c=new A3();
//FutureTask ft=new FutureTask(c);
//Thread t=new Thread(ft);
//t.start();
//如何获取线程的执行结果
Object res=ft.get(); //会阻塞当前执行线程,并等待子线程执行完成后获取返回值
优点:可以获取返回值,可以抛出异常
缺点:代码编写较为复杂
4、使用线程池
基础原理是享元模式
享元模式Flyweight Pattern主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式
优点:大大减少对象的创建,降低系统内存的使用,以提高程序的执行效率。
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。