/*
模拟ATM取款,不是线程同步机制,多线程同时对一个账户进行操作
t1 和 t2
异步编程模型:t1线程执行t1,t2线程执行的是t2,两个线程之间谁也不等于谁
同步编程模型:t1线程和t2线程执行,当t1线程必须等于t2的线程执行结果之后,t1线程才能执行
这是同步编程模型。
什么时候需要引入同步
1. 为了数据安全,尽管应用程序的使用率低,但是为了保证数据安全性,必须的加入线程同步机制
线程同步机制 使程序变成了(等同)单线程
2. 在什么条件下需要使用线程同步
<1> 必须是多线程环境
<2> 多线程环境在共享同一个数据时
<3> 共享的数据涉及到修改操作
*/
public class ThreadTest01{
public static void main(String[] args){
// 创建一个公共账户
Account act = new Account("Ming",10000.0);
// 创建线程对同一个账户进行取款
Thread t1 = new Thread(new Ming01(act));
Thread t2 = new Thread(new Ming01(act));
t1.start();
t2.start();
}
}
// 取款的线程
class Ming01 implements Runnable{
// Account 账户
Account act;
Ming01(Account act){
this.act = act;
}
public void run(){
act.withdraw(2000.0);
System.out.println("取款2000.0¥成功,余额为:" + act.getBalance());
}
}
// 银行账户
class Account{
private String actno;
private double balance; // 账户余额
public Account(){}
public Account(String actno,double balance){
this.actno = actno;
this.balance = balance;
}
public void setActno(String actno){
this.actno = actno;
}
public String getActno(){
return actno;
}
public void setBalance(double balance){
this.balance = balance;
}
public double getBalance(){
return balance;
}
// 对外提供一个取款方法
public void withdraw(double money){
// 对账户进行取款操作
double after = balance - money;
// 延迟
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
// 更新账号余额
this.setBalance(after);
}
}
//输出取款2000.0¥成功,余额为:8000.0
/*
以下程序使用线程同步机制保证数据安全型
*/
public class ThreadTest02{
public static void main(String[] args){
// 创建一个公共账户
Account act = new Account("ming",10000.0);
// 创建线程对同一个账户进行取款
Thread t1 = new Thread(new Ming01(act));
Thread t2 = new Thread(new Ming01(act));
t1.start();
t2.start();
}
}
// 取款的线程
class Ming01 implements Runnable{
// Account 账户
Account act;
Ming01(Account act){
this.act = act;
}
public void run(){
act.withdraw(2000.0);
System.out.println("取款2000.0¥成功,余额为:" + act.getBalance());
}
}
// 银行账户
class Account{
private String actno;
private double balance; // 账户余额
public Account(){}
public Account(String actno,double balance){
this.actno = actno;
this.balance = balance;
}
public void setActno(String actno){
this.actno = actno;
}
public String getActno(){
return actno;
}
public void setBalance(double balance){
this.balance = balance;
}
public double getBalance(){
return balance;
}
// 对外提供一个取款方法
public void withdraw(double money){
/*
需要把同步的代码,放到同步的语句块中
t1线程执行到此处,遇到了 synchronized关键字,就会去找this的对象锁
如果找到了this的对象锁,则进入同步语句块 执行程序。
当同步语句块代码执行结束的时候,t1线程归还this的对象锁
在t1线程执行同步语句块的过程中,如果t2线程也过来执行以下代码,遇到synchronized关键字
所以也去找this对象锁,但是该对象被t1线程持有
只能在等待this对象的归还
*/
synchronized(this){
// 对账户进行取款操作
double after = balance - money;
// 延迟
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
// 更新账号余额
this.setBalance(after);
}
}
}
/*
以下程序使用线程同步机制保证数据安全型
*/
public class ThreadTest03{
public static void main(String[] args){
// 创建一个公共账户
Account act = new Account("ming",10000.0);
// 创建线程对同一个账户进行取款
Thread t1 = new Thread(new Ming01(act));
Thread t2 = new Thread(new Ming01(act));
t1.start();
t2.start();
}
}
// 取款的线程
class Ming01 implements Runnable{
// Account 账户
Account act;
Ming01(Account act){
this.act = act;
}
public void run(){
act.withdraw(2000.0);
System.out.println("取款2000.0¥成功,余额为:" + act.getBalance());
}
}
// 银行账户
class Account{
private String actno;
private double balance; // 账户余额
public Account(){}
public Account(String actno,double balance){
this.actno = actno;
this.balance = balance;
}
public void setActno(String actno){
this.actno = actno;
}
public String getActno(){
return actno;
}
public void setBalance(double balance){
this.balance = balance;
}
public double getBalance(){
return balance;
}
// 对外提供一个取款方法
// synchronized关键字 添加到成员方法上,线程拿走的也是this对象锁
public synchronized void withdraw(double money){
/*
需要把同步的代码,放到同步的语句块中
t1线程执行到此处,遇到了 synchronized关键字,就会去找this的对象锁
如果找到了this的对象锁,则进入同步语句块 执行程序。
当同步语句块代码执行结束的时候,t1线程归还this的对象锁
在t1线程执行同步语句块的过程中,如果t2线程也过来执行以下代码,遇到synchronized关键字
所以也去找this对象锁,但是该对象被t1线程持有
只能在等待this对象的归还
*/
//synchronized(this){
// 对账户进行取款操作
double after = balance - money;
// 延迟
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
// 更新账号余额
this.setBalance(after);
//}
}
}
/*
定义一个用户线程
*/
public class UserThread01{
public static void main(String[] args){
Runnable r1 = new UserTest();
Thread t1 = new Thread(r1,"t1");
t1.start();
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " : " + i);
}
System.out.println("主线程结束 !");
}
}
class UserTest implements Runnable{
public void run(){
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " : " + i);
}
}
}
/////////////////////////////////////////////////////////////////////////
/*
守护线程
其他所有的用户线程结束,则守护线程退出
守护线程一般都是无限执行的
设置了守护线程以后,当前主线程结束后,守护线程并没有把所有的数据输出就结束
也就是说 守护线程是为 用户线程服务的,当用户线程全部结束,守护线程会自动结束
跟我们的 java中自动垃圾回收机制GC 是一个原理
*/
public class UserThread02{
public static void main(String[] args){
Thread t1 = new UserTest();
t1.setName("t1");
// 将t1这个用户线程 修改成守护线程
t1.setDaemon(true);
t1.start();
// 主线程
for(int i = 0; i < 10; i++){
System.out.println(Thread.currentThread().getName() + " : " + i);
try{
Thread.sleep(1000);
} catch(InterruptedException e){}
}
System.out.println("主线程结束 !");
}
}
class UserTest extends Thread{
public void run(){
int i = 0;
while(true){
i ++;
System.out.println(Thread.currentThread().getName() +" : "+i);
try{
Thread.sleep(1000);
} catch(InterruptedException e){
}
}
}
}
/*
Timer定时器
*/
import java.util.*;
import java.text.*;
public class TimerTest{
public static void main(String[] args){
Timer t = new Timer();
try{
Date d = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2015-1-20 23:35:30");
// 安排在指定的时间执行指定的任务
// t.schedule(new MyTimer(),d,1000*60*60*24); 24小时执行一次
t.schedule(new MyTimer(),d,1000*2);
} catch(NullPointerException e){
e.printStackTrace();
} catch(IllegalArgumentException e){
e.printStackTrace();
} catch(IllegalStateException e){
e.printStackTrace();
} catch(ParseException e){
e.printStackTrace();
}
}
}
class MyTimer extends TimerTask{
public void run(){
System.out.println(new Date());
}
}