匿名内部类方式实现线程的创建
接下来介绍使用匿名内部类方式创建线程
使用线程的匿名内部类方式,可以方便地实现每个线程执行不同的线程任务操作。
使用匿名内部类的方式实现Runnable接口,重写Runnable接口中的run方法:
public class NoNameInnerClassThread{
public static void main(String []agrs){
Runnable r=new Runnable(){
public void run(){
for(int i=0; i<20;i++){
System.out.println("张宇:"+i);
}
}
};
new Thread(r).start();
for(int i=0; i<20;i++){
System.out.println("费玉清:"+i);
}
}
}
线程安全
如果有多个线程在同时运行,而这些线程可能会同时运行一段代码,同时执行相同的任务,程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
线程安全问题都是由全局变量及静态变量引起的,若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都要考虑线程同步。
线程同步
当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题,要解决上述多线程并发访问一个资源的安全性问题,Java中提供了同步机制(synchronized)来解决。
为了保证每个线程都能正常执行院子操作,Java引入了线程同步机制,有下列三种方式完成同步操作:
1. 同步代码块。
2. 同步方法。
3. 锁机制。
*** 同步代码块**:synchronized关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。
synchronized(同步锁){需要同步操作的代码}
同步锁:对象的同步锁只是一个概念,可以想象为在对象上标记一个锁。
1. 锁对象可以是任意类型。
2. 多个线程对象要使用同一把锁。
注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着。
同步方法:使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。
public synchronized void method(){ 可能会产生线程安全问题的代码 }
同步锁:java.util.concurrent.locks.Lock机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块和同步犯非法具有的功能Lock都有,除此之外更强大的是更体现面向对象。
* public void lock():加同步锁
* public void unlock(): 释放同步锁
Timed Waiting(计时等待)
Timed Waiting在API中描述为:一个正在显示等待另一个线程执行一个(唤醒)动作的线程处于这一状态。
当我们在run方法中添加了sleep语句,这样就强制当前正在执行的线程休眠(暂停执行),以减慢线程。当我们调用sleep哦方法之后,当前执行的线程就进入到休眠状态,其实就是所谓的Timed Waiting。
注意:sleep()方法中指定的时间是线程不会运行的最短时间,因此,sleep()方法不能保证该线程睡眠到期后就开始立刻执行。
BLOCKED(锁阻塞)
Blocked状态在API中的介绍为:一个正在阻塞等待一个监视器锁(锁对象)的线程处于这一状态。
线程A与线程B代码中使用同一锁,如果线程A获得到锁,线程A进入到Runnable状态,那么B线程就进入到Blocked锁阻塞状态。
没有获得锁对象,就会进入到阻塞状态,直到得到锁对象的线程执行完毕,归还锁对象,如果没有抢到锁对象则继续等待。
Waiting(无限等待)
waiting状态在API中介绍为:一个正在无限期的等待另一个线程执行一个特别的(唤醒)动作的线程处于这一状态。
一个调用了某个对象的Object.wait方法的线程会等待另一个线程调用此对象的Object.notify()方法或Object.notifyAll()方法。
obj.wait();无限等待
obj.wait(5000);计时等待5秒,时间到了自动醒来
其实waiting状态并不是一个线程的操作,它体现的是多个线程间的通信,可以理解为多个线程之间的协作关系,过个线程会争取锁,同时相互之间又存在协作关系。就好比在公司里你和你的同事们,你们可能存在晋升时的竞争,但是更多时候你们是一起合作完成某些任务。
当多个线程协作时,比如A线程,B线程。如果A线程在Runnable(可运行)状态中调用了wait()方法那么A线程就进入了Waiting(无限等待)状态,同时失去了同步锁(同步锁将还回)。加入这个时候B线程获取到了同步锁,在运行状态中调用了notify()方法,那么就会将无限等待的A线程唤醒。注意是唤醒,如果获取到锁对象,那么A线程唤醒后就进入Runnable(可运行)状态;如果没有获取锁对象,那么就进入到Blocked(锁阻塞状态)。