1:Java有三种线程实现:
继承Thread类;也是实现了Runnable接口,Thread类也是Runnable接口的子类。
实现Runnable接口;是@FunctoinalInterface,函数式接口,只有唯一一个抽象方法。interface的方法默认是public的。不存在默认权限。
实现Callable接口;Callable接口是为了解决Runnable不能有返回值的。
native关键字说明其修饰的方法是一个原生态方法,方法是在用其他语言实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口调用其他语言来实现对底层的访问。JNI的实现就是编写native方法。
多线程的每个主题类必须复写run() 方法;
start()通过同步块保护,并判断了线程的状态。该函数调用了一个native 函数start0(),JNI(Java Native Interface)。通过它调用操作系统API。因为线程必须通过JVM由系统分配管理资源。
多线程一定依靠Thread类的start方法。故Runnable的对象必须通过new Thread(Runnable).start();Thread 类有构造函数接受Runnable对象。
Callable接口实现的。FutureTask的构造可以传入Callable对象实现。再通过Thread的start启动。newThread( new FutureTask( new Callable()))).start
2:线程的命名与取得:
线程的名字应该在启动前定义,不应该重命名线程。
A:在通过Thread的构造传入name参数;
B:通过setName设置名字;
C:在run()中通过Thread的静态方法currentThread取得当前Thread对象,再通过getName取得名字;静态方法:因为当前只可能有一个Thread在cpu。
要取得与当前线程有关的内容,必须通过Thread的静态方法currnetThread,再逐渐取得属性。publicstatic Thread currentThread()
一个JVM进程至少打开2个线程:main,gc
3:线程休眠:
sleep() 被中断休眠以后,会抛出异常。
yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。不会释放lock标志。
线程的几种状态:
新建:new一个Thread对象或者其子类对象就是创建一个线程;
就绪:新建的对象调用start方法,就开启了线程;
运行:当线程对象获取到了CPU的资源。
冻结:运行过程中的线程由于某些原因(比如wait,sleep),释放了执行资格和执行权。
死亡:当线程对象调用的run方法结束,或者直接调用stop方法。
4:线程优先级:
主线程是中等优先级;
5:线程的同步与死锁:
sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,把执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
synchronized:可以通过同步代码块以及同步方法使用。
一旦线程拥有了Synchronized对象,就可以多次重入,如递归。
守护线程setDaemon(boolean on)的特点:
守护线程开启后和前台线程共同抢夺cpu的执行权,开启、运行两者都没区别,但结束时有区别,当主线程结束,守护线程会自动结束。
多线程join方法:
特点:当A线程执行到B线程的join方法时,A就会等待B线程都执行完,A才会执行.
Java的每个对象(Object和class)都关联着一个锁(有时也叫“互斥量”),这个锁在操作系统中称为“信号量”,互斥(“mutex“)是一个二进制的信号量(有别于整型信号量)。JAVA每个对象(Object/class)都关联一个监视器,监视器的互斥功能就是依靠锁实现的。
线程的监视器,即线程所持有的锁,也就是synchronized所关联的对象。线程的互斥由线程的监视器机制来实现。
监视器分为对象监视器与线程监视器。
“在JVM中,每个对象和类在逻辑上都是和一个监视器相关联的”
“为了实现监视器的排他性监视能力,JVM为每一个对象和类都关联一个锁”
“锁住了一个对象,就是获得对象相关联的监视器”
synchronized是唯一实现同步的东西。对于下面的java程序:
synchronized(obj)
{
... ...
}
在class中将被翻译成
monitorenter(obj)
...
monitorexit(obj)
如果某个synchronized方法是static的,那么当线程访问该方法时,它锁的并不是synchronized方法所在的对象,而是synchronized方法所在的类所对应的Class对象。Java中,无论一个类有多少个对象,这些对象会对应唯一一个Class对象,因此当线程分别访问同一个类的两个对象的两个static,synchronized方法时,它们的执行顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始。