java并发编程实战wwj----------------------第一阶段--------------01-02-03-04-05-06-07-08-09-10

目录。   

   

-------------------------------------01------------------------------------------

15个知识点:

第一阶段:

进程,线程,协程

--------------------------------------02--------------------------------------------

代码:chapter1

package chapter1My;

public class TryConcurrency {

    public static void main(String[] args) throws InterruptedException {
//        readFromDataBase();
//        writeDataToFile();
//        Thread t1 = new Thread("threadname"){
//            @Override
//            public void run() {
//                try {
//                    for(int i=0;i<1000;i++){
//                        System.out.println(111);
//                        Thread.sleep(1000L);
//                    }
//
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//            }
//        };
//        t1.start();
//        Thread.sleep(1000*100L);
//        println("223");
        new Thread("read"){
            @Override
            public void run(){
                readFromDataBase();
            }
        }.start();
        new Thread("write"){
            @Override
            public void run(){
                writeDataToFile();
            }
        }.start();
    }

    private static void readFromDataBase() {
        try {
            println("Begin read data from db.");
            Thread.sleep(1000 * 30L);
            println("Read data done and start handle it.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        println("The data handle finish and successfully.");
    }
    private static void writeDataToFile() {
        try {
            println("Begin write data to file.");
            Thread.sleep(2000 * 20L);
            println("Write data done and start handle it.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        println("The data handle finish and successfully.");
    }
    private static void println(String message) {
        System.out.println(message);
    }
}

创建线程的方法

1.直接new Thread重写里面的run方法,因为Thread是implements的Runnable的。

2.new Thread(new Runnable);

注意的点:Runnable调用run方法,里面有while循环的,循环调用的是一个方法,方法里面加锁。

锁池和等待池:https://www.cnblogs.com/tiancai/p/9371655.html

创建线程的方法:https://blog.csdn.net/qq_36390044/article/details/79274800

----------------03-------------------

线程的生命周期:

  

在start的时候我们做了什么事情呢?

看下start的方法:

public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();//native方法 是C++的 这个去调用run方法
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

看下run方法:

首先理解下这个设计模式(模版方法),算法已经定了但是其中的一些的逻辑是多变的。

package one.chapter1;

public class TemplateMethod {

    public final void print(String message) {//必须是final的子类是不可以去复写的
        System.out.println("################");
        wrapPrint(message);
        wrapPrint1(message);
        System.out.println("################");
    }

    protected void wrapPrint(String message) {
        System.out.println(555);
    }

    protected void wrapPrint1(String message) {

    }

    public static void main(String[] args) {
        TemplateMethod t1 = new TemplateMethod(){
            @Override
            protected void wrapPrint(String message) {
                System.out.println("*"+message+"*");
            }

            @Override
            protected void wrapPrint1(String message) {
                System.out.println("*"+message+"*");
            }
        };
        t1.print("Hello Thread");

        TemplateMethod t2 = new TemplateMethod(){
            @Override
            protected void wrapPrint(String message) {
                System.out.println("+"+message+"+");
            }

            @Override
            protected void wrapPrint1(String message) {
                System.out.println("+"+message+"+");
            }
        };

        t2.print("Hello Thread");

    }
}

模版方法:https://www.runoob.com/design-pattern/template-pattern.html

总结: new runnable(ready running) block wait timewait treminate

还有一个是执行run方法的线程。

线程安全的get豆子:

多线程操作变量肯定是有问题的,第一个是刷新的问题,第二个是原子问题。

package chapter1.chapter1My;

public class GetBean {
    public static void main(String[] args) {
        new Thread(){
            public void run(){
                try {
                    while(true){
                        getBean();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        new Thread(){
            public void run(){
                try {
                    while(true){
                        getBean();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
        new Thread(){
            public void run(){
                try {
                    while(true){
                        getBean();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
    public static int index = 100;

    public static void getBean() throws InterruptedException {
//        synchronized (GetBean.class){
//            if(index!=0){
//                Thread.sleep(10);
//                index--;
//            }
//        }
        if(index!=0){
            Thread.sleep(10);
            index--;
        }
        if(index==0){
            return;
        }
        System.out.println(Thread.currentThread().getName()+"当前还有"+index+"个豆子");
    }

}

改为runnable的

package chapter1.chapter1My;

public class getBeanRunnable {
    public static void main(String[] args) {
        new Thread(new DoRunn()){
        }.start();
        new Thread(new DoRunn()){
        }.start();
        new Thread(new DoRunn()){
        }.start();
    }

    public static int index = 100;

    public static void getBean() throws InterruptedException {
//        synchronized (GetBean.class){
//            if(index!=0){
//                Thread.sleep(10);
//                index--;
//            }
//        }
        if(index!=0){
            Thread.sleep(10);
            index--;
        }
        if(index==0){
            return;
        }
        System.out.println(Thread.currentThread().getName()+"当前还有"+index+"个豆子");
    }

    public static class DoRunn implements Runnable{
        @Override
        public void run() {
            try {
                while(true){
                    getBeanRunnable.getBean();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

runnable里面循环调方法

方法单独写

thread在new时候传参数为runnable实例

-------------------------04----------------------------------

模拟银行排队叫号:

代码:charapter2

代码:

熟悉下lambda表达式的写法。

是无序的,重复的。

i++会去主存拿但是可能其他的线程还没有刷新到主存。

--------------------------------------05----------------------------------------

Runnable的抽取。

代码:

小实验:线程本地更新缓存。

线程的三大特性:https://www.cnblogs.com/losemyfuture/p/9375336.html

线程的可见行问题:https://blog.csdn.net/ren421259121/article/details/90447853

-----------------------------06---------------------------------------------

Thread涉及到的策略模式。

代码:charapter2/calculator

策略模式的写法:

public class TaxCalculatorMain {

    public static void main(String[] args) {
        /*TaxCalaculator calculator = new TaxCalaculator(10000d, 2000d) {

            @Override
            public double calcTax() {
                return getSalary() * 0.1 + getBonus() * 0.15;
            }
        };
        double tax = calculator.calculate();
        System.out.println(tax);*/

        TaxCalaculator calculator = new TaxCalaculator(10000d, 2000d, (s, b) -> s + 0.3 + b * 0.1);//可以改变里面的逻辑不是改变了是重写了方法
        System.out.println(calculator.calculate());
    }
}

函数式编程。

-----------------------07-------------------

代码:charapter3

Thread:main线程是JVM创建的。

 public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }
  private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;

        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

Thread的命名规则是什么?

看下这个方法:

 private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }

是静态方法。

是通过这个构造函数的。

  public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

----

看下start方法:

public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

看其中的start0,其中的start0会调用run()方法。

 @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

可以看到如果没有传runnable就要复写run方法。

如何在构造的时候就有一个名字呢?

线程和线程组的概念:

 private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
        if (name == null) {
            throw new NullPointerException("name cannot be null");
        }

        this.name = name;

        Thread parent = currentThread();
        SecurityManager security = System.getSecurityManager();
        if (g == null) {
            /* Determine if it's an applet or not */

            /* If there is a security manager, ask the security manager
               what to do. */
            if (security != null) {
                g = security.getThreadGroup();
            }

            /* If the security doesn't have a strong opinion of the matter
               use the parent thread group. */
            if (g == null) {
                g = parent.getThreadGroup();//看这个代码
            }
        }

        /* checkAccess regardless of whether or not threadgroup is
           explicitly passed in. */
        g.checkAccess();

        /*
         * Do we have the required permissions?
         */
        if (security != null) {
            if (isCCLOverridden(getClass())) {
                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
            }
        }

        g.addUnstarted();

        this.group = g;
        this.daemon = parent.isDaemon();
        this.priority = parent.getPriority();
        if (security == null || isCCLOverridden(parent.getClass()))
            this.contextClassLoader = parent.getContextClassLoader();
        else
            this.contextClassLoader = parent.contextClassLoader;
        this.inheritedAccessControlContext =
                acc != null ? acc : AccessController.getContext();
        this.target = target;
        setPriority(priority);
        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        /* Stash the specified stack size in case the VM cares */
        this.stackSize = stackSize;

        /* Set thread ID */
        tid = nextThreadID();
    }

注意这个代码:

 if (g == null) {
                g = parent.getThreadGroup();
            }

注意一点,start之后又两个线程存在的,一个是调用start方法的线程,一个是start之后的线程。

就是谁把你start了,谁就是你的parent线程。

g为null就找父亲的ThreadGroup。

看下这段代码:

执行这个代码是3。

改造下:

--------------------------08----------没看好----------------------------

线程组,ThreadGroup怎么使用是以后再讲的。

看下官方文档:

stackSize:这个参数是高度的依赖于平台的。

---

本地方法栈:NIO C++

10个线程就开辟10个虚拟机栈。

栈细分为多个栈帧,一个线程是一个栈,线程调用一次方法就有一个栈帧压栈。

代码:chapter3/CreateThread3

start0:放在本地方法栈。

栈帧有宽度和深度:10M 一个栈帧1M  深度就是10。

stackSize:创建线程改变当前线程对应的栈的深度。方法执行一次就压栈。

设置栈的深度。

package chapter3;

/***************************************
 * @author:Alex Wang
 * @Date:2017/2/16 QQ:532500648
 * QQ交流群:286081824
 ***************************************/
public class CreateThread4 {

    private static int counter = 1;

    public static void main(String[] args) {

        Thread t1 = new Thread(null, new Runnable() {
            @Override
            public void run() {
                try {
                    add(1);
                } catch (Error e) {
                    System.out.println(counter);
                }
            }

            private void add(int i) {
                counter++;
                add(i + 1);
            }
        }, "Test", 1 << 24);
        t1.start();
    }
}

-----------------09---10-------------------------没看好----------

王文君的博客:https://blog.csdn.net/wangwenjun69?viewmode=list

看下博客:JVM

指针就是4个字节。

启动jvm的时候栈空间就已经确定了,栈是方法独有的。

栈帧宽度大了那深度就小了。

栈:https://blog.csdn.net/holybin/article/details/37344671

创建栈。

创建构造Thread的时候传入stackSize代表该线程占用的stack的大小。如果没有指定stackSize的大小默认是0。0代表会忽略该参数。该参数会被JNI参数去调用,另外注意该参数再有些平台有效,有些平台是无效的。

-Xss10M设置。

栈的理解:https://www.cnblogs.com/heihaozi/p/11741733.html

stackSize的理解:https://blog.csdn.net/qq_32524177/article/details/88641950

----------------------------------------11------------------------------------------

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值