1) 什么是线程?
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。
2) 线程和进程有什么区别?
线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。
3) 如何在Java中实现线程?
继承java.lang.Thread
实现Runnable接口
4) Runnable相对于Thread的优势在哪?
java不允许多继承,因此实现了Runnable接口的类可以再继承其他类。
方便资源共享,通过实现Runnable可以共享一个对象实例
5) Thread 类中的start() 和 run() 方法有什么区别?
start()方法被用来启动新创建的线程,而且start()内部调用了run()方法。run()方法只是在原来的线程中调用,并没有新的线程启动。
6) 什么是线程安全?
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
7) 如何在两个线程间共享数据?
通过实现Runnable接口或者通过阻塞队列
8) Java中notify和 notifyAll有什么区别?
notify会唤醒所有等待线程里的某一个,notifyAll会唤醒所有等待线程,并允许它们争夺锁。
9) Thread中interrupted和 isInterrupted方法的区别?
两个方法都是用来判断当前线程是否中断。不同的是interrupted会清除中断状态,isInterrupted却不会。
10) 为什么wait和notify方法要在同步块中调用?
只有在调用线程拥有某个对象的独占锁时,才能够调用该对象的wait(),notify()和notifyAll()方法。否则,代码会抛出IllegalMonitorStateException异常。
11) Java中堆和栈有什么不同?
栈是一块和线程紧密相关的内存区域。每个线程都有自己的栈内存,用于存储本地变量、方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。而堆是所有线程共享的一片公用内存区域,对象都在堆里创建。为了提升效率,线程会从堆中弄一个缓存到自己的栈,如果多个线程使用该变量就可能引发问题,这时volatile 变量就可以发挥作用了,它要求线程从主存中读取变量的值。
12)什么是线程池? 为什么要使用它?
创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。
- 通过join方法阻塞线程
import java.util.concurrent.TimeUnit;
public class Test3 {
public static void main(String[] args) throws InterruptedException {
for(int i=0; i<3; i++){
Thread th = new MyThread();
th.start();
th.join();
}
System.out.println("All finished");
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is runninng");
try {
TimeUnit.SECONDS.sleep(Math.round(Math.random() * 3));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 通过单线程的线程池实现线程串行执行
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Test5 {
public static void main(String[] args) {
ExecutorService pool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 3; i++) {
pool.submit(new TestRunnable("thread-" + i));
}
pool.shutdown();
}
}
class TestRunnable implements Runnable {
private String name;
public TestRunnable(String name) {
this.name = name;
}
@Override
public void run() {
try {
System.out.println("Thread " + name + " is running");
TimeUnit.SECONDS.sleep(Math.round(Math.random() * 3));
System.out.println("Thread " + name + " finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
- 线程里面开启线程,并通过join阻塞
import java.util.concurrent.TimeUnit;
public class Test4 {
public static void main(String[] args) throws InterruptedException {
Thread th = new MyThread3();
th.start();
}
}
class MyThread1 extends Thread {
@Override
public void run() {
System.out.println("Thread1 is runninng");
}
}
class MyThread2 extends Thread {
@Override
public void run() {
Thread th = new MyThread1();
th.start();
try {
th.join();
TimeUnit.SECONDS.sleep(Math.round(Math.random() * 3));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread2 is runninng");
}
}
class MyThread3 extends Thread {
@Override
public void run() {
Thread th = new MyThread2();
th.start();
try {
th.join();
TimeUnit.SECONDS.sleep(Math.round(Math.random() * 3));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread3 is runninng");
}
}