精华内容
下载资源
问答
  • 主要介绍了android主线程和子线程之间消息传递详解,主线程发送消息到子线程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • c++主线程和子线程

    千次阅读 多人点赞 2020-01-29 10:04:08
    一.main()函数是主线程函数,在main()函数中创建的线程属于子线程,那主线程和子线程的优先级谁更高呢? 可以看下另外一篇文档:link 在一个线程中开启另外一个新线程,则新开线程称为该线程的子线程,子线程初始...

    c++主线程和子线程

    最近在学习c++多线程,写一篇博客记录下自己的收获。
    一.main()函数是主线程函数,在main()函数中创建的线程属于子线程,那主线程和子线程的优先级谁更高呢?
    可以看下另外一篇文档:link
    在一个线程中开启另外一个新线程,则新开线程称为该线程的子线程,子线程初始优先级与父线程相同。不过主线程先启动占用了cpu资源,如果存在主线程和子线程争抢cpu执行权的话,看运气,谁抢到就让谁执行。
    其实设置了优先级,也无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。 线程的优先级用1-10之间的整数表示,数值越大优先级越高,默认的优先级为5。
    下面来看一段简单的代码:

    #include "stdafx.h"
    #include <iostream>
    #include "process.h"
    #include "windows.h"
    using namespace std;
    
    void ThreadFun1(void *){
    	cout << "这是子线程1" << endl;
    }
    void ThreadFun2(void *){
    	cout << "这是子线程2" << endl;
    }
    int main(){     	
    	_beginthread(ThreadFun1, 0, NULL); 
    	_beginthread(ThreadFun2, 0, NULL);    
    	cout << "end" << endl;
    	return 0;  
    }
    

    这里定义了两个线程函数,并在主线程main()中创建了两个子线程。于是,此进程中有三个子线程,任一时刻cpu只运行一个进程,当cpu轮换到此进程时,到此会执行三个线程中哪一个呢?
    多次运行结果如下:
    在这里插入图片描述
    可见,主线程总是能优先获得cpu的执行权,且主线程执行完成后,程序就退出了,子线程就再也没有执行的机会,即主线程结束,子线程也会被迫结束
    为了让主线程获得cpu的执行权之后,程序不退出,可以在主线程中加入一个死循环,代码如下:

    #include "stdafx.h"
    #include <iostream>
    #include "process.h"
    #include "windows.h"
    using namespace std;
    
    void ThreadFun1(void *){
    	cout << "这是子线程1" << endl;
    }
    void ThreadFun2(void *){
    	cout << "这是子线程2" << endl;
    }
    int main(){     	
    	_beginthread(ThreadFun1, 0, NULL); 
    	_beginthread(ThreadFun2, 0, NULL);  
    	cout << "end" << endl;
    	while(1){}
    	return 0;  
    }
    

    这样在第一回合的cpu争夺中,主线程获得执行权后程序也不会退出,在后续的cpu争夺回合中,子线程便有机会获得cpu的执行权。 程序的执行结果如下:
    在这里插入图片描述在这里插入图片描述
    第一次争夺中,主线程获得cpu执行权,然后执行循环,后续争夺中,某一回合子线程1或者2获得执行权(这里由于子线程内容较少,在一次时间片轮换中就把子线程执行完毕,即只要获得一次cpu执行权就可以执行完子线程),然后退出线程池,剩下的一个子线程和主线程继续争夺cpu的执行权,后面某一个回合中,剩下子线程也执行完毕,只剩下了主线程,便一直执行主线程中的循环。
    而且也可以看出,两个子线程的执行顺序不定,即哪个子线程能先获得cpu的执行权得看运气。

    二、如果想先执行子线程,然后执行主线程,应该采用什么方法?
    这里介绍一个Sleep()函数,Sleep()函数的解释可以看这篇博客:link
    大致内容如下:
    当调用Sleep函数的时候,比如Sleep(400);它告诉系统,此线程将放弃此次运行的时间片,比方说现在线程只执行了10ms,按“有关部门规定”它被唤醒一次是要执行20ms的。这时它就说,这次机会我放弃,后面的10ms不要了。下次轮上我再叫我。 这样,系统便会将其终止,然后再一次进行调度选择。如果它运气很好,又被选中了,系统则会查看这个线程是否处于sleep标志中。如果发现他还需要继续睡眠,则重新进行调度选择,直到选择一个有权执行的线程为止。 如果很不幸,400ms到了,但是系统很忙,调度算法在很长一段时间也没有选择到这个线程,那这么线程就很继续休眠。于是说,这个Sleep(400);将导致这个线程会休眠大于等于400MS的时间。

    关于这个函数更具权威的解释(抄书):
    1、调用Sleep,可使线程自愿放弃它剩余的时间片。
    2、系统将在大约的指定秒数内使线程不可高度。不错,如果告诉系统,想睡眠100MS,那么可以睡大约这么长的时间,但也也可能睡眠数秒或数分钟。记住,WINDOWS不是个实时操作系统。虽然线程可能在规定的时间被唤醒,但是它能否做到,取决于系统中还有什么操作正在进行。
    3、可以调用Sleep(INFINITE),告诉系统永远不要调用这个线程。但最好不要这样,让线程退出就行了。反正你都不再需要它。或者调用Sleep(0);告诉系统线程将放弃剩于的时间片,并使系统调度另一个线程。但是,系统可以对刚刚调用Sleep的线程重新调度。如果不存在多个拥有相同优先级的可调度线程。就会出现这种情况。

    加入Sleep()函数后的代码如下:

    #include "stdafx.h"
    #include <iostream>
    #include "process.h"
    #include "windows.h"
    using namespace std;
    
    void ThreadFun1(void *){
    	while (1) {
    		cout << "这是子线程1" << endl;
    		Sleep(30);
    	}
    }
    int main(){     	
    	_beginthread(ThreadFun1, 0, NULL); 
    	Sleep(300);
    	cout << "end" << endl;
    }
    

    在这里插入图片描述
    可以这么理解:主线程Sleep 300毫秒,在这300毫秒内,程序只能执行子线程,然而子线程执行完打印后,也进入Sleep(30),可以认为时是每30毫秒执行一次子线程。
    如果把Sleep(30)放在cout之前;子线程执行9次,这个细微的差别请读者自行理解 。
    最后可以让三个线程依次执行:

    #include "stdafx.h"
    #include <iostream>
    #include "process.h"
    #include "windows.h"
    using namespace std;
    
    void ThreadFun1(void *){
    	cout << "这是子线程1" << endl;
    }
    void ThreadFun2(void *) {
    	Sleep(30);
    	cout << "这是子线程2" << endl;
    }
    
    int main(){     	
    	_beginthread(ThreadFun1, 0, NULL); 
    	_beginthread(ThreadFun2, 0, NULL);
    	Sleep(300);
    	cout << "end" << endl;
    }
    

    运行结果如下:
    在这里插入图片描述
    写在最后:
    Sleep()函数并不能严格保证线程按顺序执行,如上面的程序,如果子线程1内容很多,代码无法在30毫秒内完成,因此当子线程2休眠完毕后,两个子线程依然会继续争夺cpu。故无法保证线程能按顺序执行。

    展开全文
  • 主要为大家详细介绍了Android主线程和子线程的区别,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 多线程和queue配合使用,实现子线程和主线程相互通信的例子 ''' import threading __author__ = "Kenny.Li" import Queue import time import random q = Queue.Queue() class MyThread(threading.Thread): def __...
  • 主线程和子线程的区别

    千次阅读 2017-10-12 09:51:58
    主线程和子线程的区别每个线程都有一个唯一标示符,来区分线程中的主次关系的说法。 线程唯一标示符:Thread.CurrentThread.ManagedThreadID; UI界面Main函数均为主线程。 被Thread包含的“方法体”或者“委托”...

    主线程和子线程的区别

    每个线程都有一个唯一标示符,来区分线程中的主次关系的说法。
    线程唯一标示符:Thread.CurrentThread.ManagedThreadID;

    1. UI界面和Main函数均为主线程。
    2. 被Thread包含的“方法体”或者“委托”均为子线程。
    3. 委托可以包含多个方法体,利用this.Invoke去执行。
    4. 也可以定义多种方法体,放在Thread里面去执行。则此方法体均为子线程。注意如果要修改UI界面的显示。则需要使用this.Invoke,否则会报异常。
    5. Main函数为主线程,id标示符与UI界面主线程相等
      不多说了。看下面的测试代码注释吧。
    public delegate void dele();
        public partial class Form1 : Form
        {
            int idA;
            public dele getlab;
            public Form1()
            {
                InitializeComponent();
                idA  = Thread.CurrentThread.ManagedThreadId;//UI界面主线程
                /*
                 * Main函数为主线程,id标示符与UI界面主线程相同。
                 */
            }
    
            Thread thread;
            private void getbtu_Click(object sender, EventArgs e)//UI控件属于主线程
            {
                int idB = Thread.CurrentThread.ManagedThreadId;
                getlab = new dele(getLabel);//委托添加方法
                getlab += new dele(gg);//委托在叠加一个方法
                getlab += new dele(kk);//委托在叠加一个方法
                //
                thread = new Thread(new ThreadStart(delegate
                {
                    int idC = Thread.CurrentThread.ManagedThreadId;//Thread开辟一个子线程
                    //gg();//方法直接在thread里面调用均为子线程
                    //kk();//方法直接在thread里面调用均为子线程
                    getlab();//委托直接在thread里面调用,委托里面的方法为子线程
    
                    //以上因为都包含在thread里面
                    MessageBox.Show("显示完成");
    
                    //this.Invoke(getlab);
                    /*错误提示:主线程调用主线程当然会假死*/
                }));
                thread.IsBackground = true;
                thread.Start();
            }
            public void kk()//委托中的方法  委托方法三
            {
                int idR = Thread.CurrentThread.ManagedThreadId;
                this.Invoke((dele)(() =>//修改UI界面值则需要加this.Invoke
                {                 
                        label2.Text = "ABC";
                }));
            }
            public void gg()//委托中的方法  委托方法二
            {
                int idP = Thread.CurrentThread.ManagedThreadId;
                this.Invoke((dele)(() =>//修改UI界面值则需要加this.Invoke
                {
                        label3.Text = "QWE";
                }));
            }
            public void getLabel()//委托中的方法 委托方法一
            {       
                int idD = Thread.CurrentThread.ManagedThreadId;//子线程
    
                for (int i = 0; i <= 1000; i++)
                {
                    Thread.Sleep(10);
                    //this.Invoke为主线程,执行子线程的内容
                    this.Invoke((dele)(() =>
                    {
                        getlabel.Text = i.ToString();
                        int idE = Thread.CurrentThread.ManagedThreadId;//主线程
                        Console.WriteLine("线程idE:" + idE);
                    }));
                    Console.WriteLine(i);
                }
                MessageBox.Show("显示完成");
            }
    
            private void sleepbtu_Click(object sender, EventArgs e)//UI控件属于主线程
            {
                int idF = Thread.CurrentThread.ManagedThreadId;
                try
                {
                    if (thread.ThreadState != ThreadState.Suspended)
                    {
                        thread.Suspend();
                    }
                }
                catch (Exception r)
                {
                    MessageBox.Show(r.Message);
                }
            }
    
            private void setbtu_Click(object sender, EventArgs e)//UI控件属于主线程
            {
                int idG = Thread.CurrentThread.ManagedThreadId;
                try
                {
                    if (thread.ThreadState != ThreadState.Running)
                    {
                        thread.Resume();
                    }
                }
                catch (Exception r)
                {
                    MessageBox.Show(r.Message);
                }
            }
    
            public void getlabel_Click(object sender, EventArgs e)
            {
    
            }
        }

    总结:

    1. 什么是子线程?
    包含在 Thread thread = new Thread(new ThreadStart(delegate{}));里面均视为子线程。
    2. 什么是主线程?
    当一个程序启动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行,该线程通常叫做程序的主线程(Main Thread),因为它是程序开始时就执行的,如果你需要再创建线程,那么创建的线程就是这个主线程的子线程。每个进程至少都有一个主线程,在Winform中,应该就是创建GUI的线程。
    主线程的重要性体现在两方面:
    1.是产生其他子线程的线程;
    2.通常它必须最后完成执行比如执行各种关闭动作。

    展开全文
  • android主线程和子线程的区别

    千次阅读 2018-06-06 21:26:35
    android 主线程和子线程有什么区别本文较为深入的分析了android中UI主线程子线程。分享给大家供大家参考。具体如下:在一个Android 程序开始运行的时候,会单独启动一个Process。默认的情况下,所有这个程序中的...

    android 主线程和子线程有什么区别


    本文较为深入的分析了android中UI主线程与子线程。分享给大家供大家参考。

    具体如下:在一个Android 程序开始运行的时候,会单独启动一个Process。默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast Receiver)都会跑在这个Process。

    一个Android 程序默认情况下也只有一个Process,但一个Process下却可以有许多个Thread。在这么多Thread当中,有一个Thread,我们称之为UI Thread。

    UI Thread在Android程序运行的时候就被创建,是一个Process当中的主线程Main Thread,主要是负责控制UI界面的显示、更新和控件交互。

    在Android程序创建之初,一个Process呈现的是单线程模型,所有的任务都在一个线程中运行。因此,我们认为,UI Thread所执行的每一个函数,所花费的时间都应该是越短越好。而其他比较费时的工作(访问网络,下载数据,查询数据库等),都应该交由子线程去执行,以免阻塞主线程。

    那么,UI Thread如何和其他Thread一起工作呢?

    常用方法是:诞生一个主线程的Handler物件,当做Listener去让子线程能将讯息Push到主线程的Message Quene里,以便触发主线程的handlerMessage()函数,让主线程知道子线程的状态,并在主线程更新UI。

    例如,在子线程的状态发生变化时,我们需要更新UI。如果在子线程中直接更新UI,通常会抛出下面的异常:

    11-07 13:33:04.393: ERROR/JavaBinder(1029):android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.意思是,无法在子线程中更新UI。为此,我们需要通过Handler物件,通知主线程Ui Thread来更新界面。

    如下,

    首先创建一个Handler,来监听Message的事件:

    private final int UPDATE_UI = 1;

    private Handler mHandler = new MainHandler();

    private class MainHandler extends Handler {

    @Override

    public void handleMessage(Message msg) {

    switch (msg.what) {

    case UPDATE_UI: {Log.i("TTSDeamon", "UPDATE_UI");

    showTextView.setText(editText.getText().toString());

    ShowAnimation();

    break;

    }

    default:break;

    }

           }

               }

    或者:private Handler mHandler = new Handler(){

    @Override

    public void handleMessage(Message msg) {

    switch (msg.what) {

    case UPDATE_UI: {

    Log.i("TTSDeamon", "UPDATE_UI");

    showTextView.setText(editText.getText().toString());

    ShowAnimation();

    break;

    }

    default:break;

            }

                 }

                       }

    当子线程的状态发生变化,则在子线程中发出Message,通知更新UI。

    mHandler.sendEmptyMessageDelayed(UPDATE_UI, 0);

    在我们的程序中,很多Callback方法有时候并不是运行在主线程当中的,所以如果在Callback方法中更新UI失败,也可以采用上面的方法  。

    展开全文
  • 主线程和子线程的数据交互

    千次阅读 2019-05-22 11:34:52
    问题由来:主线程中的数据,子线程对其修改后在主线程中还能获得修改后的数据吗? 栗子: public class MainActivity extends AppCompatActivity { private static final String TAG = "123"; public static int ...

    问题由来:主线程中的数据,子线程对其修改后在主线程中还能获得修改后的数据吗?

    栗子:

    public class MainActivity extends AppCompatActivity {
        private static final String TAG = "123";
        public static int anInt = 1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 子
            new Thread(new Runnable() {
                @Override
                public void run() {
                    anInt = 2;
                    Log.i(TAG, "子线程: " + anInt);
                }
            }).start();
            // 主
                Log.i(TAG, "主线程: " + anInt);
          
        }
    }
    
    

    如上:主线程定义了anInt,子线程对其修改。我们再在主线程打印,能得到修改后的anInt = 2 吗?
    答案:不确定
    原因:线程争夺cup使用权顺序不确定,可能,子线程先获得使用权,则两个Log都打印2。当然主线程先获得使用权时主线程的log打印数值为1。

    解决方案

    1、让子线程先执行。

    比如主线程设置低优先级、主线程休息等等(不靠谱,提供一种想法吧)

    2、安卓中的Handler机制

    子线程发送消息,主线程接受消息,只有主线程收到消息再打印处理数值。
    handler使用略。。。。。。

    3、接口回调机制

    结合上栗子代码如下

    package com.example.administrator.layoutdemo.utils;
    
    /**
     * Create by SunnyDay on 2019/05/22
     */
    public interface MyCallBack {
        void onSuccess(String msg,int value);
    }
    
    
    
    
    public class MainActivity extends AppCompatActivity implements MyCallBack {
        private static final String TAG = "123";
        public static int anInt = 1;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 子
            new Thread(new Runnable() {
                @Override
                public void run() {
                    anInt = 2;
                    Log.i(TAG, "子线程: " + anInt);
                    MainActivity.this.onSuccess("aaa",anInt);
                }
            }).start();
            // 主
    
              //  Log.i(TAG, "主线程: " + anInt);
    
    
        }
    
     // 主
        @Override
        public void onSuccess(String msg,int value) {
            if (msg!=null){
                Log.i(TAG, "主线程: " + anInt);
            }
        }
    
    }
    
    

    如上子线程触发(MainActivity.this.onSuccess(“aaa”,anInt);)主线程才回调。
    原理还是等到子线程处理后主线程在处理。

    4、其他思路

    以上思路就是个人想到的思路,以及解释。总感觉使用其他的理论比如:
    1、线程间的可见性
    2、java内存区域的线程公有私有
    通过些理论来诠释下。
    线程这一块还需努力。。。。。。溜溜球!

    展开全文
  • Linux中主线程和子线程的终止次序

    千次阅读 2018-11-28 17:05:50
     (1)主线程和子线程之间没有必然的退出次序关系。主线程退出,子线程可以继续执行;子线程退出,主线程也可以继续执行。  (2)程序加载到内存中执行的时候,进程就会生成一个主线程。虽然主线程和子线程之间没...
  • Handler消息传递详解,子线程到子线程主线程子线程,子线程到主线程 三种消息,Looper,Handler工作机制详解 https://blog.csdn.net/shoneworn/article/details/80447651
  • Windows主线程和子线程的关系

    千次阅读 2017-12-10 17:04:51
    先来说下进程和线程的关系,进程是静态的,它相当于一个存放数据的空间,是放在内存中的,可以理解为一个工厂。而线程是动态来执行线程中的代码的,相当于工厂中的工人。看到执行代码你可能就会想到CPU了,没错,...
  • 主线程 和子线程的同步控制

    千次阅读 2016-08-27 17:25:47
    有道面试题 子线程循环10次 然后 主线程 循环100次 如此往复50次 通过主线程和子线程的同步实现 public class Test { public static void main(String args[]) { //子线程循环10次,主线程循环100次 如此...
  • Java中线程分为两种类型:用户线程和守护线程。 通过Thread.setDaemon(false)设置为用户线程;...主线程结束后守护线程和JVM的状态又下面第2条确定。 如果没有用户线程,都是守护线程,那么JVM结束...
  • 主要介绍了Python多线程:主线程等待所有子线程结束代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 主线程和子线程的同步控制

    千次阅读 2015-08-17 13:45:35
    一个线程的结束有两种途径,一种是象我们下面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。另外需要说明的是,一个线程不能被多个线程等待,也就是说对一个线程只能...
  • 线程中主线程子线程之间的关系

    千次阅读 2020-05-29 11:35:01
    最常见的情况,主线程中开启了一个子线程,开启之后,主线程与子线程互不影响各自的生命周期, 即主线程结束,子线程还可以继续执行;子线程结束,主线程也能继续执行。 测试代码如下: public class TestThread{ ...
  • 非常实用不解释,用了才知道 个人收藏的一部分资料将陆续给大家上传
  • 启动了多个线程的程序在关闭的时候却出现了问题,如果程序退出的时候不关闭线程,那么线程就会一直的存在,但是大多启动的线程都是局部变量,不能一一的关闭,如果调用Thread.CurrentThread.Abort()方法关闭主线程的...
  • Qt的子线程无法直接更新主UI,需要发送信号到主线程进行更新,我用的QTableWidget展示数据。
  • 这篇文章主要介绍了简单了解C语言中主线程退出对子线程的影响,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习...实际的答案是主线程退出后子线程的状态依赖于它所在的进程,如果进程没有退出
  • 主要介绍了python主线程子线程的结束顺序实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 进程和线程协程) 通俗的讲, 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配调度的一个独立单位(比如QQ是个进程、微信是个进程) 进程和线程的主要差别在于它们是...
  • Android的主线程子线程

    千次阅读 2016-10-26 00:08:07
    创建应用进程也包含了创建主线程的工作。Android中提供了一些有用使用子线程封装的类,如:HandlerThread,封装了Handler机制的实现; AsyncTask,用于执行轻量级的异步任务,并最终可以将结果更新到主线程中; ...
  • Unity异步线程调用主线程脚本程序,在Unity中异步线程调用主线程会报错,所以编写了一个Loom
  • 主线程如何捕获子线程的异常---马克-to-win java视频的介绍

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 151,981
精华内容 60,792
关键字:

主线程和子线程

友情链接: TestDrawerLayout.zip