进程:正在执行的程序。每一个进程执行都有一个顺序,改顺序称为执行路径,或者叫一个控制单元。
线程:进程中一个独立的控制单元,线程控制着进程的执行。
进程与线程的关系:
一个进程至少有一个线程(至少有一个主线程)。
扩展:JVM启动时,会启动java.exe进程。改进程至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,被称为主线程。(其实JVM启动不只一个线程,还有负责垃圾回收机制的线程)。
多线程的运行机制:
CPU在做着快速的切换,多个线程都在获取CPU的执行权,CPU执行到谁,谁就运行。我们感觉到电脑可以同时运行多个程序,实际上,在某一个时刻,只能有一个程序在运行(多核除外)。
此外,我们可以发现运行结果每次都不一样,原因是多线程的执行就是在互相争夺CPU的执行权,具有随机性。
创建线程的方法:
1.继承Thread类:
1.定义一个类继承Thread
2.复写Thread类中的run(),将自定义的代码存储咋run()做,让线程运行
3.调用线程的start()方法,开启线程,并执行线程的run()方法
**注意**:如果直接调用d.run(),仅仅是调用run(),线程创建了并没有执行。
2.实现Runnable接口:
1.定义一个类实现Runnable接口
2.覆盖Runnable的run()方法
3.创建一个Thread对象
4.将接口子类对象作为参数传递给Thread的构造函数
5.调用Thread的start()方法开启线程,并调用Runnable接口中的run()方法
两种方法的区别:
继承Thread:线程代码放在Thread子类的run()方法中
实现Runnable:线程代码放在接口子类的run()中
注意:避免了单继承的局限性,在使用多线程时,建议使用这种方式
多线程带来的安全问题:
当一个线程执行run()方法里的共享数据的代码块,还没有执行完,另外一个线程也参与进来执行,会导致共享数据的错误。
解决办法:
在多线程执行共享数据时,让一个线程执行完,其它线程不参与执行。使用synchronized来使线程同步。
线程同步的前提:
1.必须有两个以上的线程
2.多个线程使用同一个锁
使用synchronized同步,保证了同步时,只有一个线程在运行。
好处:解决了安全问题
弊端:多个线程需要判断锁,较为消耗资源
同步分类:
同步代码块:
synchronized(obj)
{
//obj表示同步监视器,是同一个同步对象
}
同步函数:
synchronized 返回值类型 方法名(参数列表) //一般不直接在run方法上加!)
{
/**…..
O SOMETHING
*/
}
注意:静态方法的默认同步锁是当前方法所在类的.class对象