1、线程的执行是抢占式的。


2、一个程序运行至少有一个进程,一个进程里可以包含多个线程,但至少包含一个线程。


3、所有线程对象都必须是Thread类或其子类的实例。


4、run方法的方法体就是代表了线程需要完成的任务,因此经常把run称为线程执行体。


5、用线程的start方法来启动该线程。


6、当Java程序开始运行之后,程序至少会创建一条主线程,主线程的线程执行体不是由run方法来确定的,而是由main方法来确定,main方法的方法体代表主线程的线程执行体。


7、使用继承Thread类的方法来创建线程类,多条线程之间无法共享线程类的实例变量。


8、使用继承Thread时获得当前线程对象比较简单,直接使用this即可,但是使用实现Runnable接口时要获得当前线程对象使用Thread.currentThread()方法。


9、当主线程结束时,其他线程不受任何影响,并不会随之结束。


10、join():让一个线程等待另一个线程完成的方法。当某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的join线程完成为止。


11、join有三种重载方式,最常见的是两种,第三种精确到微秒几乎用户不上。join():等待被join的线程执行完成,join(long millis):等待被join的线程的时间最长为millis毫秒,若在millis毫秒内,被join的线程还没有执行结束则不再等待。


12、守护线程(也称后台线程、精灵线程),JVM的垃圾回收线程就是典型的后台线程,如果所有的前台线程都死亡,后台线程会自动死亡。
可调用Thread对象的setDaemon(true)方法将制定线程设置成后台线程。setDaemon(true)必须在start()方法之前调用,否则引发IllegalThreadStateException。


13、前台线程创建的子线程默认是前台线程,后台线程创建的子线程默认是后台线程。


14、yield()方法可以让当前正在执行的线程暂停,但它不会阻塞该线程,而是将该线程转入就绪状态,yield只是让当前线程暂停一下,让系统的线程调度一次。


15、sleep和yield的区别:
①sleep方法暂停当前线程后,会给其他线程执行机会,不会理会其他线程的优先级。但是yield方法只会给优先级相同或者优先级更高的线程执行。
②sleep方法会将线程转入阻塞状态,直到经过阻塞时间才会转入就绪状态。而yield不会将线程转入阻塞状态,它只是强制当前线程进入就绪状态。
③sleep方法声明抛出InterruptedException异常,所以调用sleep方法时要么捕捉该异常,要么显示声明抛出该异常。而yield方法则没有声明抛出任何异常。
④sleep方法比yield方法有更好的可移植性,通常不要依靠yield来控制并发线程的执行。


16、每个线程默认的优先级都与创建它的父线程具有相同的优先级,在默认情况下,main线程具有普通优先级,由main线程创建的子线程也有普通优先级。


17、synchronized(obj)通常推荐使用可能被并发访问的共享资源充当同步监视器。


18、同步方法使用synchronized关键字来修饰某个方法,无须指定同步监视器,同步方法的同步监视器是this,也就是该对象本身。


19、不可变类总是线程安全的,因为它的对象的状态不可改变,可变对象状态需要额外的方法来保证其线程安全。


20、synchronized关键字可以修饰方法、可以修饰代码块,但是不恩能够修饰构造器、属性等。


21、释放同步代码块、同步方法对同步监视器的锁定的情况:
①当前同步代码块、同步方法执行结束,当前线程即释放同步监视器。
②当线程在同步代码块、同步方法中遇到break、return终止了该代码块、该方法的继续执行当前线程将会释放同步监视器。
③当线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致该代码块、该方法异常结束时将会释放同步监视器。
④当线程执行同步代码块或同步方法时,程序执行了同步监视器对象的wait()方法,则当前线程暂停,并释放同步监视器。


县城不会释放同步监视器的情况:
①线程执行同步代码块、同步方法时,程序调用Thread.sleep()、Thread.yield()方法来暂停当前线程的执行,当前线程不会释放同步监视器。
②线程执行同步代码块时,其他线程调用了该线程的suspend方法将该线程挂起,该线程不会释放同步监视器。


20、死锁:当两个线程相互等待对方释放同步监视器时就会发生死锁,JVM没有检测,也没有采用措施来处理死锁情况。一旦出现死锁,整个程序既不会发生任何异常,也不会给出任何提示。只是所有线程处于阻塞状态,无须继续。


21、wait()、notify()和notifyAll()方法是Object类的,而不是属于Thread类的,但是这三个方法必须由同步监视器对象来调用


22、wait()方法:导致当前线程等待,直到其他线程调用该同步监视器的notify()方法或者notifyAll()方法来唤醒该线程,对于带参数的wait()方法,则是等待指定时间后自动苏醒。


23、notify():唤醒在此同步监视器上等待的单个线程,如果所有线程都在此同步监视器上等待,则会选择唤醒其中一个线程,选择是任意性的。只有当前线程放弃对该同步监视器的锁定后(使用wait()方法),才可以执行被唤醒的线程。

24、notifyAll():唤醒在此同步监视器上等待的所有线程,只有当前线程放弃对该同步监视器的锁定后,才可以执行被唤醒的线程。

25、Java使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。对线程组的控制相当于同时控制这批线程。
若程序没有显示指定线程属于哪个线程组,则该线程属于默认线程组。默认情况下,子线程和创建它的父线程处于同一个线程组内,中途不能改变线程所属的线程组。

26、Java为线程提供了一些工具类,如ThreadLocal类,它代表一个线程局部变量,通过把数据方法ThreadLocal中就可以让每条线程创建一个该变量的副本,从而避免了并发访问的线程安全问题,ThreadLocal并不能代替同步机制,两者面向的问题领域不同。


27、集合当中,ArrayList、LinkedList、HashSet、TreeSet、HashMap等都是线程不安全的,即当多个线程向这些集合中放入一个元素时,可能会破坏这些集合数据的完整性被破坏,可采用Collections提供的静态方法来把这些集合包装成线程安全的集合,如synchronizedCollection、synchronizedMap/List/Set/SortedMap/SortSet等,
如果我们需要在多线程中使用线程安全的HashMap对象,可以采用如下代码:HashMap m=Collections.synchronizedMap(new HashMap())。