石家庄建立网站,汉川市城乡建设局网站,珠海做网站专业公司,烟台学校网站建设#x1f4c3;个人主页#xff1a;个人主页 #x1f525;系列专栏#xff1a;Java面试专题 1.线程和进程的区别
线程和进程都是操作系统中的概念#xff0c;它们的主要区别如下#xff1a; 资源分配#xff1a;进程是操作系统中的资源分配的基本单位#xff0c;每个进程… 个人主页个人主页 系列专栏Java面试专题 1.线程和进程的区别
线程和进程都是操作系统中的概念它们的主要区别如下 资源分配进程是操作系统中的资源分配的基本单位每个进程都有独立的内存空间、文件句柄等资源而线程是进程中的一个实体它与其他线程共享同一进程的资源。 调度进程拥有自己的调度器由操作系统负责进行调度而线程则由进程的调度器进行调度操作系统不能直接对线程进行调度。 运行效率线程相比进程来说更加轻量级创建和销毁的开销小切换上下文也更快因此线程的运行效率更高。 通信方式进程之间的通信需要经过操作系统的管道或共享内存等机制而线程之间可以直接共享同一进程的内存空间因此线程间通信更加快捷。
2.并行与并发的区别
在多核CPU的情况下
并发是同一时间应对多件事情的能力例如多个线程轮流使用一个CPU。
并行是同一时间动手做多件事情的能力例如4核CPU同时执行4个线程。 3.创建线程的方式有哪些
通过继承Thread类创建线程。需要重写run()方法启动线程时通过调用start()方法启动。通过实现Runnable接口创建线程。需要重写run()方法启动线程时将自定义类的实例作为一个参数调用Thread的构造方法得到一个线程实例再调用start()方法启动。通过实现Callable接口创建线程。需要重写call()方法启动线程时需要新建一个Callable的实例再用FutureTask实例包装它最终再包装成Thread实例调用start()方法启动并且可以通过FutureTask的get()方法来获取返回值。 使用线程池可以通过调用Executors类的静态方法创建线程池然后向线程池中提交任务来创建线程。
4.Runnable和Callable有什么区别 Runnable不会返回结果或抛出异常而Callable会返回结果或抛出异常。 Callable接口中定义的方法是call()方法而Runnable接口中定义的方法是run()方法。 Callable可以通过Future接口来获取执行结果而Runnable没有这样的机制。 Callable的call()方法可以抛出异常而Runnable的run()方法不能抛出异常。
5.run()和start()有什么区别 run()方法定义了线程的主要内容是实际执行的代码。但是当使用run()方法时代码执行在当前线程中并没有创建新线程。可以被调用多次就和普通方法一样 start()方法启动一个新线程来执行run()方法中的代码。当使用start()方法时代码将在新线程中执行并且在主线程中继续执行其他代码。只能被调用一次。
6.线程包括那些状态
Java线程包括如下状态: 新建状态(New)当线程对象被创建时它处于新建状态。 可执行状态(Runnable)当调用start()方法后线程开始执行进入可运行状态。可运行状态包括正在运行和就绪两种情况。 阻塞状态(Blocked)如果没有获取锁synchronized或lock进入阻塞状态获得锁再切换为可执行状态 等待状态(Waiting)如果线程调用wait()方法进入等待状态其他线程调用notify()唤醒后可以切换为可执行状态 计时等待状态(Timed Waiting)如果线程调用sleep(100)方法进入计时等待状态到时间后可切换为可执行状态 终止状态(Terminated)线程执行完成或者发生了未捕获的异常进入终止状态。 7.新建T1、T2、T3三个线程如何保证他们顺序执行
可以使用线程.join()方法来保证三个线程的顺序执行。具体实现方法如下
public class Main { public static void main(String[] args) { Thread t1 new Thread(new Runnable() { Override public void run() { // 线程T1的代码 System.out.println(Thread T1); } }); Thread t2 new Thread(new Runnable() { Override public void run() { // 线程T2的代码 System.out.println(Thread T2); } }); Thread t3 new Thread(new Runnable() { Override public void run() { // 线程T3的代码 System.out.println(Thread T3); } }); // 启动线程并使用join()保证顺序执行 t1.start(); t1.join(); // 等待t1执行完毕 t2.start(); t2.join(); // 等待t2执行完毕 t3.start(); t3.join(); // 等待t3执行完毕 }
}
8.notify()和notifyAll()有什么区别
notify()和notifyAll()都是Java中用于线程同步的方法但它们的使用方式和作用有所不同。
notify()这个方法用于唤醒在此对象监视器上等待的单个线程。如果有多个线程在等待它将唤醒其中一个线程。被唤醒的线程将获得锁然后执行。notifyAll()这个方法用于唤醒在此对象监视器上等待的所有线程。当一个线程在对象上调用wait()方法时它会在那个对象上等待直到其他线程在该对象上调用notify()或notifyAll()方法。当notifyAll()方法被调用时所有在该对象上等待的线程都会被唤醒所有的这些线程将尝试获取锁然后其中的一个将获得锁并执行。
简单来说notify()用于唤醒单个线程而notifyAll()用于唤醒所有等待的线程。在多线程编程中合理使用这两个方法可以帮助我们更好地控制线程的执行顺序和同步。 9.在java中wait和sleep方法的不同
在Java中wait()和sleep()方法都是用来暂停线程的执行但是它们的使用方式和效果有很大的不同。
sleep()方法这个方法是Thread类的一个静态方法。它会使当前线程暂停执行一段时间这段时间内线程不会消耗CPU资源。在指定的时间间隔之后线程会重新启动。注意sleep()方法需要一个参数这个参数是线程暂停的时间单位是毫秒。
Thread.sleep(2000); // 线程会暂停2秒
wait()方法这个方法是Object类的一个成员方法。它会使当前线程等待直到其他线程调用同一个对象的notify()或notifyAll()方法。在等待期间线程不会消耗CPU资源。注意wait()方法需要在对象上调用并且需要在一个同步上下文中。也就是说它通常被包含在一个synchronized块或者方法中。
synchronized (object) { while (condition does not hold) object.wait(); // perform action appropriate to condition
}
在这个例子中线程会等待直到condition does not hold变为false。然后线程会继续执行。
总的来说sleep()和wait()的主要区别在于
sleep()是静态方法可以在任何地方调用但它不会检查任何条件而wait()是对象的方法必须在同步上下文中调用它会检查一个条件并决定是否等待。sleep()会导致线程阻塞一段时间这段时间内线程不会消耗CPU资源而wait()会导致线程进入等待状态直到其他线程调用同一个对象的notify()或notifyAll()方法。在这段时间内线程不会消耗CPU资源。sleep()和wait()都需要一个时间参数但是这个参数的含义不同。对于sleep()它是暂停的时间对于wait()它是等待的最大时间毫秒如果在这个时间内没有接收到通知那么线程会重新竞争锁并重新检查条件。
10.如何停止一个正在运行的线程
①使用一个标志位来通知线程可以安全地终止其执行
class MyThread extends Thread { private volatile boolean running true; public void run() { while (running) { // ... do some work ... } } public void shutdown() { running false; }
}
在这个例子中当shutdown()方法被调用时线程将停止其执行。当然线程应该定期检查running变量的值并在可能的情况下安全地退出循环。这样线程就可以在适当的时候结束其执行。
②使用stop方法强行终止不推荐方法已经作废
③使用interrupt方法中断线程
在Java中你可以使用interrupt方法来尝试中断一个线程。但是你需要注意的是interrupt方法并不会立即终止线程而是会设置一个中断标记你需要在线程的中断处理代码中响应这个中断。
以下是一个简单的例子说明如何中断一个线程
public class MyThread extends Thread { public void run() { while (!Thread.currentThread().isInterrupted()) { // 线程的逻辑... } }
} public class Main { public static void main(String[] args) { MyThread myThread new MyThread(); myThread.start(); // 在需要的时候中断线程 myThread.interrupt(); }
}
在这个例子中MyThread类继承了Thread并重写了run方法。在run方法中我们在循环中检查线程是否被中断。如果线程被中断isInterrupted方法会返回true这样我们就可以退出循环。
在主方法中我们创建了一个MyThread对象并启动了线程。然后我们使用interrupt方法来中断线程。
请注意这只是一个简单的例子。在实际的程序中你可能需要在更复杂的逻辑中处理线程的中断。例如如果你的线程是在一个阻塞操作如Thread.sleep或Object.wait中那么当调用interrupt方法时线程会收到一个InterruptedException。你需要在代码中处理这个异常并响应中断。