一 线程的创建
多线程允许将程序任务分为几个并发的子任务,以提高系统的运行效率。
线程有以下几个属性:
1. 轻型实体:线程中的实体几乎不拥有系统资源。
2.独立调度和分派的基本单位:在多线程的os中。线程是独立运行的基本单位。因为其“轻”的特性。故线程之间的切换非常迅速且开销小
3 并发执行。不仅允许一个进程间的并发而且还允许多个进程间的并发执行。
4:共享进程资源
一个新建的线程他完整的生命周期中包括了 新建,就绪,运行,阻塞,死亡五个状态。
我们的java语言当然支持多线程的编程。
1,线程的创建:java中创建新线程可以通过继承Thread类来创建如
class MyThread extends Thread{
.......
public void run(){ //override父类的run方法
...........
}
}
2 通过实现Runnable接口来创建线程如
class Testtest implements Runnable{
.......
public void run(){ //override父类的run方法
...........
}
}
由于java的单继承特点。显然我们用实现Runable接口的方式更加方便。
二 线程的同步
java为线程类提供了很多方法,用起来也比较简单我在这里主要比较一下void sleep( long millis);和void wait(),查下api文档我们发现,wai()是Thread类继承父类Object类的方法。Thread.sleep(5000); 表示要线程睡眠5000毫秒,而Thread.wait();表示线程等待,等待时间未知。显然我们从传递的参数也可以看出来,而一旦对线程用了wait方法我们必须要调用notify()或者 notifyall()。才可以让线程重新获得运行。
下面我们来详细分析下同步锁的问题 synchrozied
synchrozied同步方法
通过在方法声明中加入synchrozied关键字可以声明同步方法 例如
public synchrozied void Synchrozieddemo{
}
synchroizded方法控制对对象成员的访问,每个对象对应一把锁。每个Synchronized方法都必须获得调用改方法的对象的锁后才能执行。方法一旦执行便独享该锁。直到该方法返回时才释放,然后被阻塞的线程才可以获得锁而投入运行。这种机制确保了同一时刻对于同一个类的不同对象调用synchronzied的方法的对象至多有一个处于运行状态。避免了了对成员的访问冲突。
public class Readd {
public static void main(String[] args) {
Mythread t1 = new Mythread();
Mythread t2 = new Mythread();
Mythread t3 = new Mythread();
t1.start();
t2.start();
t3.start();
}
}
class Mythread extends Thread {
public void run() {
for( int i= 5; i>0;i--){
try {
Thread.sleep(100);
}catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" “+ i);
}
}
}
这个程序的运行结果为
Thread-1 3
Thread-0 3
Thread-2 3
Thread-1 2
Thread-0 2
Thread-2 2
Thread-1 1
Thread-0 1
Thread-2 1
显然结果并不能让我们满意,假如这是应用在银行或者售票系统方面,肯定会导致冲突 我们可以使用同步方法来解决这个问题,可以将程序改成
public class Readd {
public static void main(String[] args) {
Thread t1=new Thread (new Mythread());
Thread t2=new Thread (new Mythread());
t1.start();
t2.start();
}
}
class Mythread implements Runnable{
static int i= 3;
public void run() {
while(true){
sale();
}
}
public synchronized void sale(){
if(i>0){
try{
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" " + i--);
}
}
或者使用同步代码块 只需要将希望同步的方法放入到Synchronized(this ){ .....}中便好了。参数使用this表示将监视器放到了这个对象身上,这样可以与同步方法一起同步,因为同步方法的监视器也是这个对象。
三 线程的死锁:
产生死锁的必要条件
1 互斥条件
2请求和保持条件
3不可剥夺条件
4环路等待条件
在编程时如果某方法或者代码块要监视多个对象时一定要注意线程的死锁,避免进入死等状态!