java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口
Thread类是在java.lang包中定义的,一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限
详见:http://developer.51cto.com/art/201203/321042.htm
知识点一、实现自定义线程类
// 实现自定义线程类
public class SubRun implements Runable{
@Override
public void run(){
for( int i=0; i<50; i++){
System.out.println(Thread.currentThread().getName()):
}
}
}
// 测试类
public static void main(String[] args){
SubRun sr = new SubRun();
Thread t = new Thread(sr);
t.start();
}
知识点二、为啥非要使用start()方法启动多线程呢?
一旦调用start()方法,则会通过JVM找到run()方法
在源码中找到Thread中的start()方法,此方法中使用了private native void start0();其中native关键字表示可以调用操作系统的底层函数,那么这样的技术成为JNI技术(java Native Interface)
Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能
Java平台有个用户和本地C代码进行互操作的API称为Java Native Interface (Java本地接口)
使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的
1、为了使用底层的主机平台的某个特性,而这个特性不能通过JAVA API访问
2、为了访问一个老的系统或者使用一个已有的库,而这个系统或这个库不是用JAVA编写的
3、为了加快程序的性能,而将一段时间敏感的代码作为本地方法实现
知识点三、线程同步
简单来说有:同步代码块 同步方法(还有另外的好多种)
同步是一种高开销的操作,没有必要同步整个方法,同步关键代码即可
同步代码块 :有synchronized关键字修饰的语句块
同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。在同步代码块中调用了sleep方法并不是释放锁对象的
synchronized(obj){
//同步代码块
}
同步方法:有synchronized关键字修饰的方法
同步方法中的锁对象固定是this
静态同步方法:在方法声明上加上static synchronized
静态同步方法中的锁对象是类名.class
当synchronized修饰一个static方法时,多线程下获取的是类锁,Calss锁可以对类的所有实例起作用
当synchronized修饰一个非static方法时,多线程下获取的是对象锁(即类的实例对象)
知识点四、受阻塞和等待休眠
受阻塞:线程具有执行资格,没有CPU时间
等待和休眠:线程放弃执行资格
sleep和wait区别:
sleep是Thread类的方法 自己睡 到时间自己就醒了 sleep休眠时 不释放锁
wait是Object类方法 等待后 得notify唤醒 wait等待时 释放锁
知识点五、synchronized和Lock
1.synchronized是Java中的关键字,是jdk自带的;Lock是一个接口
2.synchronized在线程执行发生异常时,jvm会让线程释放锁,因此不会导致死锁现象发生;Lock在finally中必须通过unLock()去释放锁,不然容易造成线程死锁
3.使用synchronized时,如果A线程阻塞,B线程会一直等待,不能够响应中断;Lock可以尝试获得锁,线程可以不用一直等待,通过interrupt()方法能够响应中断(interrupt无法中断已经获取的锁,只能中断等待状态)
4.synchronized无法判断锁的状态;Lock可以知道有没有成功获取锁(可以通过其中的tryLock()等自带的多个方法去尝试获取锁)
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当多线程竞争资源非常激烈时,此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
知识点六、线程中断
1.stop()方法,在一个线程对象上调用stop()方法时,线程占用的锁被强制释放,极易导致数据的不一致性或者带锁无限休眠
2.interupt()方法,使用等待/通知机制或者给那个线程一个中断信号, 让它自己决定该怎么办
中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断
中断是通过调用Thread.interrupt()方法来做的. 这个方法通过修改了被调用线程的中断状态来告知那个线程, 说它被中断了. 对于非阻塞中的线程, 只是改变了中断状态, 即Thread.isInterrupted()将返回true; 对于可取消的阻塞状态中的线程, 比如等待在这些函数上的线程, Thread.sleep(), Object.wait(), Thread.join(), 这个线程收到中断信号后, 会抛出InterruptedException, 同时会把中断状态置回为true.但调用Thread.interrupted()会对中断状态进行复位。