java vm启动时会有一个进程java.exe,该进程至少有一个进程负责java程序的运行。
而且这个线程运行的代码就存在于main中,称为主线程。
其实jvm不只有一个线程,比如负责垃圾回收的等等。
创建线程的方法:
1.继承Thread类,重写public void run( )方法,通过子类对象.start( );启动线程。
2.实现Runable接口,覆盖Runnable接口中的run方法,通过Thread类建立线程对象。
将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
建议使用实现方式,避免单继承的局限性。
同步代码块,解决多线程安全问题。
synchronized(对象){//需要被同步的代码}
如果一整个函数需要被同步,可以将synchronized作为修饰符放在函数上。
注:
1.需要被同步的部分就是正在操作共享数据的部分。
2.存在两个及以上的线程(前提一)
3.多个线程使用同一个锁。(前提二)
4.同步函数使用的锁时this
5.静态同步函数使用的锁是类的字节码文件对象,也就是 类名.class
单例设计模式-懒汉式
由于在多线程时,存在操作共享数据的原因,故应该使用同步。
可以在函数上加锁,可以使用同步代码块。
使用同步代码块时,使用的锁是静态锁,也就是类名.class。
建议使用双重判断的形式,减少读锁操作,提高效率。
线程间通讯:
多线程操作同一资源,但是操作的动作不同。
wait()
notify()
notifyAll()
都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这些方法定义在Object类中?
因为这些方法在操作同步中线程时,都必须要标识他们所操作的线程持有的锁,
只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁。
而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
当多个线程同时操作同一个资源时,需要使用while判断标记,使用notifyAll唤醒线程。
结束线程的方式:
开启多线程运行,运行代码通常是循环结构。
只要控制住循环,就能让线程停下来,也就是结束线程。
特殊情况:
当线程处于了冻结状态(wait),就不会读取到标记,无法结束线程。
当没有指定的方式让冻结的线程恢复到运行状态时,需要对冻结进行清除。
强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
使用的就是Thread类提供的interrupt()方法,捕获InterruptException异常,并改变标
记。
守护线程(setDaemon( ))
将线程标记为守护线程(后台线程),当前台线程结束后,只剩下后台线程,后台线程自
动结束。
获取CPU执行权(join( ))
线程调用join方法后,线程获得执行权,直到线程完全执行完为止。
线程优先级
表示线程抢夺CPU的频率。当优先级设置高以后,CPU执行该线程的频率较高。
共1-10级,默认为5级。一般设置值使用1,5,10级。
Thread.yield()临时暂停正在执行的线程。
|
|