1、什么是进城和线程?
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
2、为什么用多线程?
随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程序的要求了。于是就发明了线程,线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成。而进程的切换相对线程的切换消耗大很多。
3、java怎么使用多线程?
在java中要想实现多线程,有三种方法,一是继承Thread类,二是实现Runable接口,三是实现Callable接口,并与Future、线程池结合使用(该方法使用较少,有兴趣看这里Java并发编程与技术内幕:Callable、Future、FutureTask、CompletionService )
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
//通过Runnable接口实现 class MyThread implements Runnable { private int ticket = 10; @Override public void run() { for(int x = 0; x < 100; x++) { if(this.ticket > 0) { System.out.print("卖票," + this.ticket --); } } } } public class TestDemo{ public static void main(String[] args) { MyThread mt = new MyThread(); new Thread(mt).start(); new Thread(mt).start(); new Thread(mt).start(); } }
//通过继承Thread实现多线程,未能实现数据共享 class MyThread extends Thread { private int ticket = 10; @Override public void run() { for(int x = 0; x < 100; x++) { if(this.ticket > 0) { System.out.print("卖票," + this.ticket --); } } } } public class TestDemo{ public static void main(String[] args) { MyThread mt1 = new MyThread(); MyThread mt2 = new MyThread(); MyThread mt3 = new MyThread(); mt1.start(); mt2.start(); mt3.start(); } }
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
面试题2: 一个JVM进程启动的时候至少启动几个线程?
至少启动两个线程,一是,main线程,程序的主要执行,以及启动子线程; 二是GC线程,用于垃圾收集;