创建一个线程类的方法:
1,直接继承Thread类。
class ThreadTest extends Thread
{
public void run()
{
}
}
2, 实现Runnable接口。
class ThreadTest implements Runnable
{
public void run()
{
}
}
Thread的一些方法:
setDaemon(true):设置一个线程为后台线程,该方法必须在线程启动之前调用,也就是在调用start()方法之前调用。如果一个进程中只有后台线程在运行,这个进程就会结束。
join()当前线程邀请调用方法的线程优先执行 在调用方法的线程执行 //结束之前 当前线程不能再次执行。
yield()方法可以让当前正在运行的线程对象临时暂停,让别的线程运行。
sleep(...)方法可以让当前正在运行的线程进入睡眠状态。
线程同步关键字是:synchronized
同步代码块放在如下的大括号中:
synchronized(obj)
{
//用于synchronized的obj可以是任何对象,我们通常称之为同步对象或者监视器对象。
}
同步方法只须在方法前加synchronized关键字修饰即可。
public synchronized void fun()
{
}
同步非静态方法的监视器是this,而同步静态方法的监视器是当前所在的类的Class对象。
单例模式中同步代码块的使用:
懒汉式1
if(instance == null)
{
instance = new Single();
}
return instance;
2 给懒汉添加同步
if(instance == null)
{
synchronized(Single.class)
{
instance = new Single();
}
}
return instance;
3 同步块内使用判断
synchronized(Single.class)
{
if(instance == null)
{
instance = new Single();
}
}
return instance;
4 双重判断
If(instance == null)
{
synchronized(Single.class)
{
if(instance == null)
{
instance = new Single();
}
}
}
return instance;
关于死锁:
死锁产生的条件
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
例如线程1运行代码中
synchronized(A)
{
/运行到此处
synchronized(B)
{
}
{
线程2运行代码中
synchronized(B)
{
/运行到此处
synchronized(A)
{
}}产生死锁
如何避免死锁:
通过建立获取锁定的顺序,可以避免这种死锁。当所有线程始终按指定的顺序获取锁定时,即可避免这种死锁。
死锁原则
1.请勿尝试在可能会对性能造成不良影响的长时间操作(如 I/O)中持有锁。
2.请勿在调用模块外且可能重进入模块的函数时持有锁。
3.一般情况下,请先使用粗粒度锁定方法,确定瓶颈,并在必要时添加细粒度锁定来缓解瓶颈。大多数锁定都是短期持有,而且很少出现争用。因此,请仅修复测得争用的那些锁定。
4.使用多个锁定时,通过确保所有线程都按相同的顺序获取锁定来避免死锁。
线程间的通讯:wait()、notify()、notifyAll()
wait():
等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateExcep tion。
调用任意对象的 wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。
notify():
唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。
notifyAll():
唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。
代码示例:有A、B、C三个类(三条线程),让A先执行一秒,然后执行B、C, B、C执行完后,再执行A,如此循环
package biji;
public class Test4
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
final ThreadTest test=new ThreadTest();
new Thread(new Runnable()
{
@Override
public void run()
{
while(true)
{
test.A();
// TODO Auto-generated method stub
}
}
}).start();;
new Thread(new Runnable()
{
@Override
public void run()
{
while(true)
{
test.B();
// TODO Auto-generated method stub
}
}
}).start();;
new Thread(new Runnable()
{
@Override
public void run()
{
while(true)
{
test.C();
// TODO Auto-generated method stub
}
}
}).start();;
}
}
class ThreadTest
{
boolean tagB=true;
boolean tagC=true;
public synchronized void A()
{
while((tagB && tagC)==false)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
System.out.println("A finish");
Thread.sleep(1000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
tagB=false;
tagC=false;
this.notifyAll();
}
public synchronized void B()
{
while(tagB==true)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("B finish");
tagB=true;
this.notifyAll();
}
public synchronized void C()
{
while(tagC==true)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("C finish");
tagC=true;
this.notifyAll();
}
}