JAVA多线程
从Java5之后,线程并发部分扩展了相当多的内容,做为程序员我们就要与时俱进,最近手上事不多看了下多线程的东西,发个贴总结下,希望对多线程不了解的朋友有
所帮助。线程得以扩展源于多线程大师 Doug Lea的贡献。可以通过API看到他写的注释和代码!
1.何谓多线程
多线程就是在同一应用程序中有多个顺序流同时执行任务,就像你在计算机上可以边看电影边聊天一样,看电影是播放器的一个任务聊天也是给计算器发送一个任务请
求。
2.线程的创建
线程的创建可以有两种方式:
1).继承Thread类并重写run方法
class EThread extends Thread
{
public void run()
{
...
}
}
2).实现Runnable接口
class E1Thread implements Runnable{}
Runnable中只有一个方法:
public void run(); 用以定义线程运行体。
使用Runnable接口可以为多个线程提供共享的数据。
3.线程的启动
//继承Thread类的方法可以直接调用start方法就可以启动线程
Thread t1 = new EThread();
t1.start();
有兴趣可以看下javaAPI里面Thread的start方法就是更改了started属性的变量
//实现Runnable接口的线程类必须new一个Thread类并传入自身引用
Thread t2 = new Thread(new E1Thread());
t2.start();
start()和run()的区别,如果启动一个线程必须调用start方法,调用run方法和调用普通方法没什么区别。
4. 线程同步
在Java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记保证在任一时刻,只能有一个线
程访问该对象。
当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。这里举个取款的例子说明。
public class MoneyDao
{
//取款机里面的总额度
private Integer s_count = 10000;
public void takeMoney(int t_count)
{
//锁住取款机的额度(得到锁)
synchronized (s_count)
{
s_count = s_count - t_count;
}(丢失锁)
}
}
假设线程A过来取款,到synchronized的时候线程A就拿到了MoneyDao的锁,线程B就无法访问,只能在门口等待直到线程A丢失锁,这样就保证了MoneyDao对象每时每刻只能
让一个线程访问,这就是简单的共享互斥!所以当别人问你HashMap是线程安全的还是线程不安全的时候你就可以看API里面HashMap的方法有没有被synchronized修饰!
4.线程等待wait和sleep
wait和sleep都会让线程等待,他们的区别是wait会释放锁sleep不会释放锁!就像在取款机前取款轮到你取款的时候你忘记了密码如果你打电话询问密码那么后面排队的
人和你一起陷入等待状态,这就是一个典型的sleep.如果你忘记密码离开取款机重新排队并询问密码那么这就是一个wait方法只有你会陷入等待状态,并不会影响其他人
。
/**
* @author 武林
* @param tName
* @see 线程A和线程B同时访问takeMoneys方法,如果是B访问就让线程B等待并释放锁,
* @see 线程A拿到锁后,唤醒线程B。
* @see sleep可以在方法体的任何部分
* @see wait只可以在synchronized内部,因为wait需要释放锁
*/
public void takeMoneys(String tName)
{
synchronized(MoneyDao.class)
{
try {
//判断是否是线程1访问
if(!"A".equals(tName) || "A" != tName)
{
//如果是线程B访问就释放锁对象
MoneyDao.class.wait();
}
//唤醒线程B
MoneyDao.class.notify();
System.out.println(tName);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//让程序休息1秒
try
{
new Thread().sleep(1000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}