进程是一个正在执行的程序,是操作系统管理的。 执行过程,持有资源和线程。 多线程是一个进程中多个线程,轻量级的进程,线城是进程的组成。 线程是系统中最小的单元,一个进程=>多个线程,共享内存和资源。 有两种方法, 第一种,继承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(); } }