zoukankan      html  css  js  c++  java
  • 多线程编程核心技术(一)介绍

    串行思维是一个很固化的东西,不过也很尴尬的是,处理器最早最早的时候就是串行。你说串行思想肯定是与生俱来的,特别是写代码的时候。能稍微用来一点分治的思维,代码就已经相当的有可读性了。但是多线程这东西肯定是要深刻留在大脑里面的,不然注定面试时候被敲倒。这年头其实说实话,我写代码以来就感觉这个水平是真的参差不齐。特别是随着Java越来越强大,写代码变得更加的容易。大佬封装好了一切,你主需要.api就可以成为一个合格的CRUD工程师,内心对业务了如指掌,基本上就不会被辞退。有人说现在的程序员分成了业务派和技术派。真扯淡。技术饭永远以技术为主。公司需要自己的技术护城河,同样的程序员也应该有自己的技术护城河

    这一章是写Thread类的核心方法,线程的启动,如何使线程停止,如何使线程暂停,线程的优先级,线程安全相关问题。

    线程是进程中的子任务,一个线程就是一个任务可以这么累计,左手吃饭,右手看手机,人是一个进程。

    多线程的意思就是有限时间内发挥CPU的最大性能。以前有个朋友和我说最好服务器上的CPU永远保持在80-95%之间是最好的。现在想想平滑的业务情况下,100%都没问题。

     如果CPU的能力可以在任务一和任务二之间来回切换,那么第二种情况是最好的。多线程是一个异步的,至少在逻辑上是异步的。

    首先得到一个线程的类,感受下什么是线程

    
    
    public class demo4   {

    public void run(){
    int j = 0;
    for (int i = 0; i < 1000000; i++) {
    j +=i;
    }
    }

    public void l(){
    int j = 0;
    for (int i = 0; i < 1000000; i++) {
    j +=i;
    }
    }

    public static void main(String[] args) {
    demo4 demo4 = new demo4();
    long a = System.currentTimeMillis();
    demo4.run();
    System.out.println(System.currentTimeMillis()-a);
    demo4.l();
    System.out.println(System.currentTimeMillis()-a);
    }
    }

    输出为:
    3
    6

    加上多线程之后
    public class demo4 extends Thread {
    @Override
    public void run(){
    int j = 0;
    for (int i = 0; i < 1000000; i++) {
    j +=i;
    }
    }

    public void l(){
    int j = 0;
    for (int i = 0; i < 1000000; i++) {
    j +=i;
    }
    }

    public static void main(String[] args) {
    demo4 demo4 = new demo4();
    long a = System.currentTimeMillis();
    demo4.start();
    System.out.println(System.currentTimeMillis()-a);
    demo4.l();
    System.out.println(System.currentTimeMillis()-a);
    }
    }
    输出为:
    0
    3

     这边要注意的就是就算是多线程情况下,也一定要使用.start(),如何是.run()还是无效的。

    start方法
    public synchronized void start() { if (threadStatus != 0) throw new IllegalThreadStateException(); group.add(this); boolean started = false; try {
    //真正的执行方法是这个,上面的都是check的过程。start0是一个本地方法,调用的不是java。 start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { it will be passed up the call stack */ } } }

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

      那么为什么要使用.start而不是,run呢?看上面的源码好像没有发现start和run之间的关系。run()只是接口中的一个方法,如果没有实现就无效。猜想下8成概率是和start0()方法有关系的。

    start0()方法是一个C实现的方法,run()不是开启新线程的钥匙,但是start()中的新线程会去调用这个重写的run()方法。也就是逻辑上应该是start()-->start0()-->JVM-->run()

    回忆下,静态方法,是什么时候被加载的,类加载的时候静态方法就也诞生了,start0方法对应在具体代码是下面这个。

    {"start0", "()V",(void *)&JVM_StartThread}, 然后执行了JVM_StartThread。JVM又会去创建一个新的JavaThread,到这算是真正的创建出了线程。这个新线程再调用方法,最后轮到 template(run_method_name,"run") 方法。总体有点乱,逻辑上就是

    JNIEXPORT void JNICALL 
     Java_Java_lang_Thread_registerNatives (JNIEnv *env, jclass cls){ 
       (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods)); 
     } 
     static JNINativeMethod methods[] = { 
        {"start0", "()V",(void *)&JVM_StartThread}, 
        {"stop0", "(" OBJ ")V", (void *)&JVM_StopThread}, 
    	 {"isAlive","()Z",(void *)&JVM_IsThreadAlive}, 
    	 {"suspend0","()V",(void *)&JVM_SuspendThread}, 
    	 {"resume0","()V",(void *)&JVM_ResumeThread}, 
    	 {"setPriority0","(I)V",(void *)&JVM_SetThreadPriority}, 
    	 {"yield", "()V",(void *)&JVM_Yield}, 
    	 {"sleep","(J)V",(void *)&JVM_Sleep}, 
    	 {"currentThread","()" THD,(void *)&JVM_CurrentThread}, 
    	 {"countStackFrames","()I",(void *)&JVM_CountStackFrames}, 
    	 {"interrupt0","()V",(void *)&JVM_Interrupt}, 
    	 {"isInterrupted","(Z)Z",(void *)&JVM_IsInterrupted}, 
    	 {"holdsLock","(" OBJ ")Z",(void *)&JVM_HoldsLock}, 
    	 {"getThreads","()[" THD,(void *)&JVM_GetAllThreads}, 
    	 {"dumpThreads","([" THD ")[[" STE, (void *)&JVM_DumpThreads}, 
     };


    JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) 
    	native_thread = new JavaThread(&thread_entry, sz); 


    static void thread_entry(JavaThread* thread, TRAPS) { 
        HandleMark hm(THREAD); 
    	 Handle obj(THREAD, thread->threadObj()); 
    	 JavaValue result(T_VOID); 
    	 JavaCalls::call_virtual(&result,obj, 
    	 KlassHandle(THREAD,SystemDictionary::Thread_klass()), 
    	 vmSymbolHandles::run_method_name(), 
     vmSymbolHandles::void_method_signature(),THREAD); 
     }


    class vmSymbolHandles: AllStatic { 
    	template(run_method_name,"run") 
    	}
     

    那么线程在硬件眼里是个怎么样的存在?如果调用的呢?

    我认为多线程的正确含义应该是单位时间内多个线程串行处理。如果把CPU看到最简单的一个逻辑门,那它的功能就仅仅只是进行信号的处理。一个线程分化多个任务进入逻辑门,例如加减,IO,加减,IO,加加。如果是单线程的的情况下就是这一个线程相当于一定会执行完,多线程的情况下就是IO的时候,可以再进行另外线程的任务,不让CPU休息。逻辑上单核处理器,也是具有多线程的能力的。

    smartcat.994
  • 相关阅读:
    OBS Studio使用日记——第一次使用黑屏
    了不起的网站链接
    【PTA】L1-006 连续因子 (20分)
    【PTA】L1-048 矩阵A乘以B (15分)
    【PTA】L1-034点赞
    【PTA】L1-028 判断素数 (10分)
    【PTA】L2-001 紧急救援 (25分)
    UEditor 富文本编辑器 上传图片 配置
    在存储过程中使用表变量实现批量导入
    SharePoint Designer 2013 开启新式验证(Modern Authentication)
  • 原文地址:https://www.cnblogs.com/SmartCat994/p/14179034.html
Copyright © 2011-2022 走看看