使用三个线程在一个字符后面顺序添加字符

一、先来了解一下多线程中fina域l的内存语义,大家都知道多线程并行执行时,就会出现编译器执行时并不是顺序执行代码的,因此我们必须加入一些关键字来使得我们的程序能够顺序执行,就是所谓的内存可见性,下面先来了解一下final的内存语义。

1、fina域的内存语义
遵守两个重排序规则:
(1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。
(2)初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能冲排序。
2、写final域的重排序 (其实就是使用StoreStore屏障确保final域的写是在构造函数之中的 )
(1)JMM禁止编译器把final域的写重排序到构造函数之外。
(2)编译器会在final域的写之后,构造函数return之前,插入一个StoreStore屏障。这个屏障禁止处理器把final域的写重排序到构造函数之外。
注:写final域的重排序规则可以确保:在对象引用的任意线程可见之前,对象的final域已经被正确初始化过了。
3、读final域的重排序
(1)读final域的重排序规则是,在一个线程中,初次读对象引用与初次读该对象包含的final域,JMM禁止处理器重排序这两个操作。编译器会在读final域操作的前面插入一个LoadLoad屏障。
(2)读final域的重排序规则可以确保:在读一个对象的final域之前,一定会先读包含这个final域的对象的引用。
4、final域的引用类型
(1)对于引用类型,写final域的重排序规则对编译器和处理器增加了如下约束:在构造函数内对一个final域引用的对象成员域的写入,与随后在构造函数外把这个被构造对象的引用的赋值给一个引用变量,这两个操作之间不能重排序。
5、为什么final引用不能从构造函数内溢出
原因:写final域的重排序规则可以确保:在引用变量为任意线程可见之前,该引用变量指向的对象的final域已经在构造函数中被正确初始化过了。还需一个保证:在构造函数内部中,不能让这个被构造对象的引用为其他线程所见,也就是对象不能在构造函数中 “溢出”。

二、了解完之后,通过一个案例我们可以看到final也可以让线程顺序执行,

1、三个线程同时启动,_A、_B、_C,让它们顺序追加到Hello之后。

代码可以直接运行:

public class FinalConcurrent {

    public StringBuffer Thred1(){
        Scanner cin = new Scanner(System.in);
        System.out.println("Please input number :");
        StringBuffer str = new StringBuffer(cin.next());
        final Thread A = new Thread(new Runnable() {  //线程A
            @Override
            public void run() {
                str.append("_A");
                System.out.println("AAAAAAAAAAAA");
            }
        });

        final Thread B = new Thread(new Runnable() {  //线程B
            @Override
            public void run() {
                str.append("_B");
                System.out.println("BBBBBBBBBBBB");
            }
        });
        final Thread C = new Thread(new Runnable() {  //线程C
            @Override
            public void run() {
                str.append("_C");
                System.out.println("CCCCCCC");
            }
        });
        A.start();
        B.start();
        C.start();
        try {
            sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return str;
    }

    public static void main(String[] args) {

        System.out.println(new FinalConcurrent().Thred1());
        }

}

上面的代码就可以实现线程的顺序执行,,,,,,,,,,,,,,,

原文地址:https://www.cnblogs.com/jxp0112/p/10863888.html

时间: 2024-08-30 09:11:20

使用三个线程在一个字符后面顺序添加字符的相关文章

有三个线程T1 T2 T3,如何保证他们按顺序执行-转载

T3先执行,在T3的run中,调用t2.join,让t2执行完成后再执行t3 在T2的run中,调用t1.join,让t1执行完成后再让T2执行 public class Test { // 1.现在有T1.T2.T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行 public static void main(String[] args) { final Thread t1 = new Thread(new Runnable() { @Override public voi

启动三个线程A,B,C,按ABC的顺序输出10次

package jun; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /**  * 启动三个线程A,B,C,

三个线程顺序输出

一.join介绍 Thead.join()函数在使用后,会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行.源码中调用join后,方法会一直检测要join()的线程是否存活(isAlive()方法),直到线程执行完成后,调用线程的this.notifyAll()方法,才会回到刚刚挂起的主程序.基本操作如下: public class Worker extends Thread { // 工作者名 private String name; // 工作时间 private long tim

有三个线程,怎么让他们按顺序执行?

场景:有三个线程t1.t2.t3.确保三个线程t1执行完后t2执行,t2执行完成后t3执行. 方法1:thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B. package com.gs.demo1; public class ThreadTest1 { public static void main(String[] args) { Thread t1 = new

C#编程总结(三)线程同步

C#编程总结(三)线程同步 在应用程序中使用多个线程的一个好处是每个线程都可以异步执行.对于 Windows 应用程序,耗时的任务可以在后台执行,而使应用程序窗口和控件保持响应.对于服务器应用程序,多线程处理提供了用不同线程处理每个传入请求的能力.否则,在完全满足前一个请求之前,将无法处理每个新请求.然而,线程的异步特性意味着必须协调对资源(如文件句柄.网络连接和内存)的访问.否则,两个或更多的线程可能在同一时间访问相同的资源,而每个线程都不知道其他线程的操作. "如果觉得有用,请帮顶! 如果有

[转]C#编程总结(三)线程同步

本文转自:http://www.cnblogs.com/yank/p/3227324.html 在应用程序中使用多个线程的一个好处是每个线程都可以异步执行.对于 Windows 应用程序,耗时的任务可以在后台执行,而使应用程序窗口和控件保持响应.对于服务器应用程序,多线程处理提供了用不同线程处理每个传入请求的能力.否则,在完全满足前一个请求之前,将无法处理每个新请求.然而,线程的异步特性意味着必须协调对资源(如文件句柄.网络连接和内存)的访问.否则,两个或更多的线程可能在同一时间访问相同的资源,

Java多线程:用三个线程控制循环输出10次ABC

题目:有A,B,C三个线程, A线程输出A, B线程输出B, C线程输出C,要求, 同时启动三个线程, 按顺序输出ABC, 循环10次. 解题思路:要按顺序输出ABC, 循环10次,就要控制三个线程同步工作,也就是说要让三个线程轮流输出,直到10个ABC全部输出则结束线程.这里用一个Lock对象来控制三个线程的同步.用一个int型变量state标识由那个线程输出. 1 package com.thread; 2 3 import java.util.concurrent.locks.Lock;

Java 多线程(三) 线程的生命周期及优先级

Java 多线程(三) 线程的生命周期及优先级 线程的生命周期 线程的生命周期:一个线程从创建到消亡的过程. 如下图,表示线程生命周期中的各个状态: 线程的生命周期可以分为四个状态: 1.创建状态: 当用new操作符创建一个新的线程对象时,该线程处于创建状态. 处于创建状态的线程只是一个空的线程对象,系统不为它分配资源. 2.可运行状态: 执行线程的start()方法将为线程分配必须的系统资源,安排其运行,并调用线程体——run()方法,这样就使得该线程处于可运行状态(Runnable). 这一

java多线程三之线程协作与通信实例

多线程的难点主要就是多线程通信协作这一块了,前面笔记二中提到了常见的同步方法,这里主要是进行实例学习了,今天总结了一下3个实例: 1.银行存款与提款多线程实现,使用Lock锁和条件Condition.     附加 : 用监视器进行线程间通信 2.生产者消费者实现,使用LinkedList自写缓冲区. 3.多线程之阻塞队列学习,用阻塞队列快速实现生产者消费者模型.    附加:用布尔变量关闭线程        在三种线程同步方法中,我们这里的实例用Lock锁来实现变量同步,因为它比较灵活直观.