进程是一个正在执行的程序,是操作系统管理的。
执行过程,持有资源和线程。
多线程是一个进程中多个线程,轻量级的进程,线城是进程的组成。
线程是系统中最小的单元,一个进程=>多个线程,共享内存和资源。
有两种方法,
第一种,继承thread类,第二种实现runnable接口。
Thread:继承thread定义一个线程类,只要继承Thread类,他就是一个线程类。
第二种,实现Runnable接口。
重写run方法,run中就是代码要执行的代码。
几种解决线程同步的方法:
public class Bank {
/**
* @param args
*/
private int count = 0;
//存钱
public void addMoney(int money){
count += money;
System.out.println(System.currentTimeMillis()+"存进"+money);
}
//取钱
public void subMoney(int money){
if(count - money <0){
System.out.println("余额不足");
return;
}
count -= money;
System.out.println(+System.currentTimeMillis()+"取出"+money);
}
//查询
public void lookmoney(){
System.out.println("账户余额" + count);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
第一种方法加锁
public class Bank2 {
private int count = 0;
//存钱
public synchronized void addMoney(int money){
count += money;
System.out.println(System.currentTimeMillis()+"存进"+money);
}
//取钱
public synchronized void subMoney(int money){
if(count - money <0){
System.out.println("余额不足");
return;
}
count -= money;
System.out.println(+System.currentTimeMillis()+"取出"+money);
}
//查询
public void lookmoney(){
System.out.println("账户余额" + count);
}
}
第二种:关键代码处加锁
同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。
public class Bank3 {
private int count = 0;
//存钱
public void addMoney(int money){
synchronized(this){
count += money;
}
System.out.println(System.currentTimeMillis()+"存进"+money);
}
//取钱
public synchronized void subMoney(int money){
if(count - money <0){
System.out.println("余额不足");
return;
}
synchronized(this){
count -= money;
}
System.out.println(+System.currentTimeMillis()+"取出"+money);
}
//查询
public void lookmoney(){
System.out.println("账户余额" + count);
}
}
第三种:使用volatitle
a.volatile关键字为域变量的访问提供了一种免锁机制
b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新
c.因此每次使用该域就要重新计算,而不是使用寄存器中的值
d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量
public class Bank4 {
private volatile int count = 0;
public void addMoney(int Money){
if(count - Money <0){
System.out.println("余额不足");
return;
}
count +=Money;
System.out.println(+System.currentTimeMillis() +"取出"+Money);
}
//取钱
public void subMoney(int money){
if(count - money <0){
System.out.println("余额不足");
return;
}
count -= money;
System.out.println(+System.currentTimeMillis()+"取出"+money);
}
//查询
public void lookmoney(){
System.out.println("账户余额:"+count);
}
}
第四种:
在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。
ReenreantLock类的常用方法有:
ReentrantLock() : 创建一个ReentrantLock实例
lock() : 获得锁
unlock() : 释放锁
注:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于能大幅度降低程序运行效率,不推荐使用
public class Bank5 {
private int count = 0;
//需要声明这个锁
private Lock lock = new ReentrantLock();
//存钱
public void addMoney(int money){
lock.lock();//上锁
try{
count += money;
System.out.println(System.currentTimeMillis()+"存进"+money);
}finally{
lock.unlock();//解锁
}
}
public void subMoney(int money){
lock.lock();
if(count-money <0){
lock.lock();
try{
if(count-money<0){
System.out.println("余额不足");
return;
}
}finally{
lock.unlock();
}
}
}
// 查询
public void lookMoney() {
System.out.println("账户余额:" + count);
}
}
//线程启动
public class SynThreadTest {
public static void main(String[] args) {
final Bank4 bank = new Bank4();
//存钱线程
Thread tadd = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bank.addMoney(100);
bank.lookmoney();
System.out.println("\n");
}
}
});
//取钱线程
Thread tsub =new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
bank.subMoney(100);
bank.lookmoney();
System.out.println("\n");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
//线程启动。
tsub.start();
tadd.start();
}
}