一, join 方法
1. 该方法为成员方法
2. 线程合并
- package com.bjpowernode.java_learning;
- ?
- public class D107_1_JoinMethod {
- public static void main(String[] args) throws InterruptedException{
- Thread t = new Thread (new Processer107());
- t.setName("t");
- t.start();
- // 合并线程
- t.join();//t 和主线程合并, 可以理解为两个栈合并成一个栈了, 也就是子线程与主线程合并成一个单线程了
- // 主线程
- for(int i=0;i<5;i++) {
- System.out.println(Thread.currentThread().getName()+"-->"+i);
- }
- }
- }
- class Processer107 implements Runnable{
- public void run() {
- for(int i=0;i<5;i++) {
- try {
- Thread.sleep(1000);
- }catch(InterruptedException e) {
- }
- System.out.println(Thread.currentThread().getName()+"-->"+i);
- }
- }
- }
二, 线程的同步(加锁)
1. 异步编程模型: 线程与线程之间, 独立执行, 谁也不等谁?.
2. 同步编程模型?: 线程与线程之间, 先执行一个, 再执行另一个, 有执行的先后顺序.
3.? 什么时候要同步? 为什么? 引入线程同步?
(1)? 为了数据安全, 例如: 银行取款?. 但是为了? 保证数据是安全的, 必须加入线程同步机制;
(2)? 使用线程同步的情形: i. 必须是? 多线程环境; ii. 多线程环境共享一个数据; iii.? 共享的数据涉及到修改操作.
以下程序演示取款例子(这个不使用同步的机制, 看看会产生什么影响)
- package com.bjpowernode.java_learning;
- ?
- public class D107_2_SynchronizedMethod {
- public static void main(String[] args) throws InterruptedException{
- // 创建一个公共账户
- Accout107_2 a = new Accout107_2("actno-001",8000.0);
- Processer107_2 c = new Processer107_2(a);
- // 创建线程对同一个账户进行取款
- Thread t1 = new Thread(c);
- Thread t2 = new Thread(c);
- t1.start();
- t2.start();
- }
- }
- class Accout107_2 {
- private String actno;
- private double balance;
- public Accout107_2(String actno,double balance) {
- this.actno = actno;
- this.balance = balance;
- }
- ?
- public String getActno() {
- return actno;
- }
- ?
- public void setActno(String actno) {
- this.actno = actno;
- }
- ?
- public double getBalance() {
- return balance;
- }
- ?
- public void setBalance(double balance) {
- this.balance = balance;
- }
- // 对外提供一个取款的方法
- public void withdraw(double money) {
- double after = this.balance - money;
- try {
- // 这里我们故意延迟了一下, 可以看出余额不对了
- Thread.sleep(1000);
- }catch(InterruptedException e){
- }
- this.setBalance(after);
- }
- }
- class Processer107_2 implements Runnable{
- // 账户
- Accout107_2 act;
- //Constructer
- public Processer107_2(Accout107_2 act) {
- this.act = act;
- }
- public void run() {
- act.withdraw(1000.0);
- System.out.println("取款成功, 余额为:"+act.getBalance());
- }
- }
修改一下代码, 来解决上面的问题
我们只需要修改 withdram 方法即可
- public void withdraw(double money) {
- // 把需要同步的代码, 放到同步语句块中, 参数一定要填共享对象
- synchronized(this) {
- double after = this.balance - money;
- try {
- // 这里我们故意延迟了一下, 可以看出余额不对了
- Thread.sleep(1000);
- }catch(InterruptedException e){
- }
- this.setBalance(after);
- }
- }
? 总结: 加入线程同步机制?, 可以保证我们的数据是安全的, 并且是准确, 但是这也是牺牲性能为前提的.
三, synchronized 的原理
t1 线程和 t2 线程, t1 线程执行到 synchronized 关键字, 就会找 this 对象的对象锁, 如果找到 this 对象锁, 则进入到同步语句块中执行程序, 当同步语句块中的代码执行结束汉字过后, t1 线程? 归还 this 的对象锁.
在 t1 线程执行同步语句块的过程中, 如果 t2 线程也过来执行以下代码, 也遇到了 synchronized 关键字, 所以也去找 this 的对象锁, 但是该对象锁被 t1 线程持有, 只能在这等待 this 对象锁? 归还.?
四, 源码:
D107_1_JoinMethod.java
D107_2_SynchronizedMethod.java
- https://github.com/ruigege66/Java/blob/master/D107_1_JoinMethod.java
- https://github.com/ruigege66/Java/blob/master/D107_2_SynchronizedMethod.java
- 2.CSDN:https://blog.csdn.net/weixin_44630050
3. 博客园: https://www.cnblogs.com/ruigege0000/
来源: http://www.bubuko.com/infodetail-3500169.html