关于java多线程的基础知识

 1.线程和进程的区别

进程是正在运行的程序实例,每个进程包含了多个线程,每个现场执行不同的任务

进程都有自己的内存空间,而一个进程下的线程们则是共享内存空间

线程更加轻量,线程上下文切换的成本远低于进程上下文切换的成本

2025.01.09补

进程|线程|协程

进程是资源分配的最小单位,有自己的独立空间。PCB是进程的唯一标识可以看做是应用程序运行的载体

线程是CPU任务调度和执行的最小单位,一个进程中有多个线程,可以并发运行,共享进程提供的相同的代码与数据空间,有自己独立的运行栈和程序计数器,切换开销很小

协程又称微线程,是一种用户态的轻量级线程,一个线程可以有多个协程,可以不加锁的访问全局变量

 

2.并行与并发的区别

并行是多核CPU一般执行相应个数的线程

并发是线程轮流使用一个或多个CPU,在单CPU的状态下,微观上讲其实他是串行的

 

3.创建线程都有哪些方式

extends Thread

public class MyThread extends Thread{
    ......
}

MyThread thread=new MyThread();

implement Runnable

pubic class MyRunnable implement Runnable{
    .......
}

MyRunnable runnable=new MyRunnable();
Thread thread=new Thread(runnable);

implement Callable<T>

public class MyCallable implement Callable<T>{
    public T call(){
        ....
        return T;
    }
}

MyCallable callable=new MyCallable();
FutureTask<T> task=new FutureTask(callable);
Thread t=new Thread(task);
...
t.start();
...
//调用task的get方法可以获取执行结果
T res=task.get()

线程池创建线程

public class MyExecutors implements Runable{
    .......
}

// 创建线程池对象
ExecutorService executorPool=Executors.newFiexedThreadPool(3);
threadPool.submit(new MyExecutors());

// 关闭线程池
threadPool.shutdown

 

4.实现runnable和实现callable有什么区别?

  1. callable是有返回值的,可以用Future、FutureTask拿到执行的结果
  2. run()是不允许抛异常的,但是call()是可以抛的

 

5.线程执行的run()和start()方法有什么区别

run方法是直接执行了被封装的代码,是可以执行多次的

start方法是启动线程,该方法只能调用一次,多次会抛出异常。不过start方法也是调用run方法内的逻辑

 

6.线程包含了哪些状态/线程的生命周期

生命周期包括五部分:新建(new),就绪(runnable),运行(running),阻塞(blocked),死亡(dead)

新建->运行->( 阻塞 等待 时间等待 )->终止

new一个线程之后是新建状态

调用start()方法后线程进入运行状态;在方法体内sync抢不到锁进入阻塞状态,获得锁后返回运行状态;有sleep()就是进入时间等待状态,;有wait()方法就是进入等待状态,notify()方法唤醒后进入运行状态

线程抢到了CPU执行权,start结束后就是终止状态

 

7.如何保证线程按顺序执行

线程具有join()方法,具体为等待某线程结束后,该线程才可以执行

Thread t1 = new Thread(() -> {
            System.out.println("t1 is run....");
        });
        Thread t2 = new Thread(() -> {
            try {
                t1.join();//直到t1运行结束之后t2才会运行
                System.out.println("t2 is run....");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }


        });
        t2.start();
        t1.start();

 

8.什么是notify和notifyAll

notify是随机唤醒一个wait线程;notifyAll是唤醒所有wait线程

 

9.说说wait和sleep的不同

wait(),wait(long)和sleep(long)都能让当前线程暂时放弃cpu的使用权,进入阻塞状态;

sleep是静态方法,可以直接用,wait方法是Object成员的方法,每个对象都有

wait()和wait(long)都可以被notify唤醒;sleep(long)、wait(long)都会在等待相应时间后被唤醒;都可以被打断唤醒

wait必须要配合锁来使用(比如sync锁)sleep无限制;wait执行后会释放CPU使用权,给其他线程使用sleep如果在sync锁内,即使sleep了CPU使用权也未释放

 

10.如何停止一个正在运行的线程

使用flag,让线程正常退出(在线程外指定位置终止while(xxx)条件)

使用interupt方法中断线程,打断sleep,wait,join的线程会抛异常;打断正常线程和第一种情况一样

 

11.thread.sleep(0)究竟有什么用

sleep(0)是立即放弃当前时间片,让调度器重新选择下一个要运行的线程

sleep(0)和yield()

在行为上:sleep是明确让出当前时间片,yield则是建议调度器重新考虑线程调度;

在状态上:sleep后线程会进入time_waiting(阻塞)状态,而yield仍然会让线程处于runnable状态

yield是提出释放时间片的请求,实际处理是由JVM实现的。释放时间片但是线程仍然不会释放锁,依旧处于runnable状态

posted @ 2024-10-14 20:32  天启A  阅读(12)  评论(0)    收藏  举报