1. 进程的概念:进程是指运行中的程序。
2. 线程的概念:线程是指进程中的一个执行流程,有时也称为执行场景。一个进程可以由多个线程组成,即使在一个进程中可以同事运行多个不同的线程,它们分别执行不同的任务。
3. main主线程:运行“java XXX”命令,就启动一个java虚拟机进程,java虚拟机进程就会创建一个main主线程,该线程从程序入口main()方法开始执行。
4. 创建和启动线程的第一种方式:
(1) 定义继承Thread类的Monkey类,覆盖Thread类的run()方法。
(2) 创建并启动monkey线程:
Monkey monkey = new Monkey(“小悟空”);
monkey.start();
Thread类的start()方法用于启动线程。monkey线程启动后,会自动运行monkey对象的run()方法。
5. 创建和启动线程的第二种方式:
(1) 定义实现Runnable接口的Monkey类,实现Runnable接口的run()方法。
(2) 创建并启动能执行monkey对象的run()方法的线程:
Monkey monkey = new Monkey(“小悟空”);
Thread thread = new Thread(monkey);
Thread.start();
Thread类的start()方法用于启动线程。以上thread线程启动后,会自动运行monkey对象的run()方法。
6. 线程在生命周期中所处的状态:
(1) 新建状态:用new语句创建的线程对象处于新建状态。
(2) 就绪状态:当一个线程对象创建后,其他线程调用它的start()方法,该线程就进入就绪状态。
(3) 运行状态:处于这个状态的线程占用CPU,执行程序代码。只有处于就绪状态的线程才有机会转到运行状态。
(4) 阻塞状态:线程因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才有机会转到运行状态。
(5) 死亡状态:当线程执行完run()方法中的代码,或者遇到了未捕获的异常,就会退出run()方法,此时就进入死亡状态,该线程结束生命周期。
7. 程序如何干预java虚拟机对线程的调度过程
(1) 调度各个线程的优先级。
(2) 让处于运行状态的线程调用Thread.sleep()方法。
(3) 让处于运行状态的线程调用Thread.yield()方法。
(4) 让处于运行状态的线程调用另一个线程的join()方法。
8. Thread类的currentThread()静态方法返回当前线程对象的引用。所谓当前线程,就是正在执行该currentThread()静态方法的线程。
9. 原子操作的概念:原子操作包含一组相关的操作,假定原子操作需要操纵对象obj的实例变量a,为了保证得到正确的运算结果,必须保证一个线程在执行原子操作的过程中,不允许其他线程操纵对象obj的实例变量a。
10. 多个线程对共享资源的竞争:当多个线程同时执行各自的原子操作,而这些原子操作都操纵相同的资源,会导致一些线程执行原子操作时运算出错。
11. 线程同步机制:假定t1线程执行原子操作code1,与此同时,t2线程执行原子操作code2。code1和code2都操纵共享资源对象obj。为了避免对共享资源的竞争,code1和code2都被加上了synchronized(obj)标记,即synchronized(obj){code1}。Code1和code2被称为同步代码块,只有获得对象obj的锁的线程才能执行同步代码块。任何时候只允许有一个线程持有对象obj的锁,这样就保证只有当一个线程执行完自己的同步代码块,其他线程才有机会获得锁,执行自己的同步代码块。由于受到锁的牵制,t1线程和t2线程无法同时执行各自的同步代码块,这样就避免了对共享资源对象obj的竞争。
12. 线程通信的机制:
假定t1线程执行同步代码块code1,t2线程执行同步代码块code2.code1和code2都操纵共享资源对象obj,因此都采用对象obj的锁来同步。当t1线程执行同步代码块code1时,如果执行obj.wait()方法,t1线程就会释放对象obj的锁,进入对象obj的等待池中等待被唤醒。
当t2线程执行同步代码块code2时,如果执行obj.notify()方法,在obj的等待池中的t1线程就会被唤醒,t1线程被转移到对象obj的锁池中。
当t2线程执行完同步代码块code2,就释放对象obj的锁。此时,位于对象obj的锁池中的t1线程获得对象obj的锁,继续执行code1同步代码块的后续代码。