java线程相关

1.why?
在程序中如果没有主动创建,只会存在一个主线程(但是在JVM中不止一个线程,还有诸如垃圾回收等)
所以为了提升性能aka加速,java开发中通常需要创建线程

2.how?
方法一:继承Thread类并重写run()

public class TestDemo{
    public static void main(String args[]) {
        new ThreadTest().start();   //新建一个实例并调用start()开始线程
    }
}
class ThreadTest extends Thread{    //创建一个继承Thread的新类
    static int[] i = {0,1,2,3};
    @Override
    public void run() {     //新线程的入口,本质上也是实现了runable接口
        for(int x:i)
        {
            System.out.println(x);
        }
    }
}

方法二:继承Runable接口并重写run()

public class TestDemo{
    public static void main(String args[]) {
        RunnableTest r = new RunnableTest();    
        new Thread(r,"thread_1").start();
        new Thread(r,"thread_2").start();
    }
}
class RunnableTest implements Runnable{
    static int[] i = {0,1,2,3};
    @Override
    public void run() {
        for(int x:i)
        {
            System.out.println(x);
        }
    }
}

方法三:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class TestDemo{
    public static void main(String args[]) {
        CallableTest c = new CallableTest();//创建 Callable 实现类的实例
        FutureTask<Integer> f = new FutureTask<>(c); //FutureTask 类来包装Callable对象,并封装返回值
        new Thread(f).start(); //使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程

        try {
           //调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。
            System.out.println("子线程的返回值: " + f.get()); //FutureTask对象的get()要配合异常捕获语句使用
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}
class CallableTest implements Callable{  //通过继承Callable接口创建实现类
    static int[] i = {0,1,2,3};
    @Override
    public Integer call() throws Exception{ //重写的call()方法将作为线程执行体,并且有返回值
   //throws Exception放在方法后边,表示的是本方法不处理异常,交给被调用处处理
        int t = 0;
        for(int x:i)
        {
            System.out.println(x);
            t++;
        }
        System.out.println(Thread.currentThread().getName() + " is running");
        return t;
    }
}

3.优劣比较
直接继承Thread类并重写run方法:编写简单,访问当前线程无需使用 Thread.currentThread() 方法,直接使用 this 即可;但已经继承了Thread,就不可以继承其他父类
runnable/callable:可以实现多继承,多个线程可以共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想

runnable与callable的区别:
(1) Callable重写的是call(),Runnable重写的是run()。

(2) Callable的任务执行后可返回值,而Runnable不能。

(3) call方法可以抛出异常,run方法不可以。

(4) 运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果

全部评论

相关推荐

02-09 16:14
武汉大学 Java
1.&nbsp;问一下本科经历2.&nbsp;介绍一下你第一个项目3.&nbsp;DDD分层架构比传统的MVC有哪些好处?4.&nbsp;你设计的业务分配的算法介绍一下?5.&nbsp;算法有哪些优化思路?6.&nbsp;动态标签列设计怎么思考的?7.&nbsp;数据量有多大?8.&nbsp;数据量很大的话,数据存储怎么优化?9.&nbsp;如何保证缓存和数据库之间的数据一致性?10.&nbsp;相对于你这个项目用哪种方案?11.&nbsp;项目中遇到的最大的困难是什么?12.&nbsp;介绍一下第二个项目13.&nbsp;模型分析diff的上下文怎么考虑?14.&nbsp;如果diff的关联的上下文很长超过token,你会怎么办?15.&nbsp;你想的这种方案,最后输入给模型的prompt是什么?16.&nbsp;对于大模型的其他组件如RAG和skills有了解吗?17.&nbsp;那你有想过把代码拆分成一些知识库放在rag里面吗?18.&nbsp;有对比过其他模型的分析效果吗?19.&nbsp;golang有了解吗?20.&nbsp;HashMap的底层结构21.&nbsp;为什么要用红黑树?22.&nbsp;红黑树增删的时间复杂度?23.&nbsp;MySQL事务隔离级别24.&nbsp;MVCC实现原理25.&nbsp;手撕算法:lc402&nbsp;移掉k位数字&nbsp;-&gt;&nbsp;没想到单调栈,暴力枚举了QAQ反问面试官之后,感觉我的缺点主要在于项目太过于玩具了,对于高并发什么的思考处于比较浅的地步,还有就是code-review对于call&nbsp;graph还有一些成熟的方案不怎么了解过,相当于纯demo,面过几场才知道QAQ,估计是没啥希望了,继续沉淀了噶人们
查看25道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务