精华内容
下载资源
问答
  • 最近一个小功能,具体逻辑是通过代码读取datahub数据并把获取到的数据产出成数据文件。因为数据量较大,所以考虑到使用多线程来运行。下面是主要代码 线程启动方法 public void start() throws Exception { ...

    最近在做一个小功能,具体逻辑是通过代码读取datahub数据并把获取到的数据产出成数据文件。因为数据量较大,所以考虑到使用多线程来运行。下面是主要代码
    线程启动方法

        public void start() throws Exception {
            String shardId = "0";
            String name = "ThreadShardOne";
            ThreadReadDataHub shardOne = new ThreadReadDataHub(name, shardId);
            shardOne.start();
            logger.info("线程》"+name+"已经启动");
    
            shardId = "1";
            name = "ThreadShardTwo";
            ThreadReadDataHub shardTwo = new ThreadReadDataHub(name, shardId);
            shardTwo.start();
            logger.info("线程》"+name+"已经启动");
            System.out.println("线程》"+name+"已经启动");
    
    //        shardId = "2";
    //        name = "ThreadShardThree";
    //        ThreadReadDataHub shardThree = new ThreadReadDataHub(name, shardId);
    //        shardThree.start();
    
        }

    读取datahub代码

      /**
         * 每个文件的最大数据条数
         *
         * @param maxSize
         */
        public void start(Integer maxSize, String shardId) throws Exception {
    
            long start = System.currentTimeMillis();
            List<String> result = new ArrayList<>();
            //默认130000
            if (maxSize == null || maxSize <= 0) {
                maxSize = 30000;
            }
    
            boolean bExit = false;
            GetTopicResult topicResult = client.getTopic(projectName, topicName);
            // 首先初始化offset上下文
            OffsetContext offsetCtx = client.initOffsetContext(projectName, topicName, subId, shardId);
            String cursor = null; // 开始消费的cursor
            if (!offsetCtx.hasOffset()) {
                // 之前没有存储过点位,先获取初始点位,比如这里获取当前该shard最早的数据
                GetCursorResult cursorResult = client.getCursor(projectName, topicName, shardId, CursorType.OLDEST);
    //            GetCursorResult cursorResult = client.getCursor(projectName, topicName, shardId, System.currentTimeMillis() - 24 * 3600 * 1000 /* ms */);
    
                cursor = cursorResult.getCursor();
    
            } else {
                // 否则,获取当前已消费点位的下一个cursor
                cursor = client.getNextOffsetCursor(offsetCtx).getCursor();
            }
    //        logger.info("Start consume records, begin offset context:" + offsetCtx.toObjectNode().toString()
    //                + ", cursor:" + cursor);
    
            long recordNum = 0L;
            int limit = 30000;
            while (!bExit) {
                try {
                    GetRecordsResult recordResult = client.getRecords(projectName, topicName, shardId, cursor, limit,
                            topicResult.getRecordSchema());
    
                    List<RecordEntry> records = recordResult.getRecords();
                    if (records.size() == 0) {
    
                        if (result.size() > 0) {
                            //生成文件
                            TextUtils.writeText(result, fileName,filePath);
                            result.clear();
    
                            logger.info("获取订阅数据至写入文件共耗时>>>>>>>>>>>>>>>>>" + (System.currentTimeMillis() - start) + "毫秒");
                            logger.info("###########################shardId=" + shardId + "###########################");
                            start = System.currentTimeMillis();
                        }
    
                        // 将最后一次消费点位上报
                        client.commitOffset(offsetCtx);
    //                    logger.info("commit offset suc! offset context: " + offsetCtx.toObjectNode().toString());
                        // 可以先休眠一会,再继续消费新记录
    //                    thread.sleep(1000);
                        logger.info("sleep 1s and continue consume records! shard id:" + shardId);
                    } else {
                        if (!records.isEmpty()) {
    
                            for (RecordEntry record : records) {
                                // 处理记录逻辑
                                // System.out.println("Consume shard:" + shardId + " thread process record:"
                                //        + record.toJsonNode().toString());
    
                           result.add(
    
                                        record.getBigint("111") + common
                                        + record.getString("222") + common
                                        + record.getBigint("333") + common
                                        + record.getBigint("444") + common
                                        + record.getDouble("555") + common
                                        + record.getBigint("666") + common
                                        + record.getBigint("777") + common
                                        + record.getBigint("888") + common
                                        + record.getBigint("999") + common
                                        + record.getString("1212")
                                );
    
                                if (result.size() == maxSize) {
                                    //生成文件
                                    TextUtils.writeText(result, fileName,filePath);
    
                                    result.clear();
                                    logger.info("获取订阅数据至写入文件共耗时>>>>>>>>>>>>>>>>>" + (System.currentTimeMillis() - start) + "毫秒");
                                    logger.info("###########################shardId=" + shardId + "###########################");
                                    start = System.currentTimeMillis();
                                }
    
    
                                // 上报点位,该示例是每处理100条记录上报一次点位
                                offsetCtx.setOffset(record.getOffset());
                                recordNum++;
                                if (recordNum % 100 == 0) {
                                    client.commitOffset(offsetCtx);
    //                                logger.info("commit offset suc! offset context: " + offsetCtx.toObjectNode().toString());
                                }
                            }
                        }
                        cursor = recordResult.getNextCursor();
                    }
                } catch (SubscriptionOfflineException e) {
                    // 订阅下线,退出
                    bExit = true;
                    logger.error("订阅下线,退出"+e.getMessage());
                    throw new Exception(e);
                } catch (OffsetResetedException e) {
                    // 点位被重置,更新offset上下文
                    client.updateOffsetContext(offsetCtx);
                    cursor = client.getNextOffsetCursor(offsetCtx).getCursor();
    //                logger.info("Restart consume shard:" + shardId + ", reset offset:"  + offsetCtx.toObjectNode().toString() + ", cursor:" + cursor);
                    logger.error("点位被重置,更新offset上下文"+e.getMessage());
                } catch (OffsetSessionChangedException e) {
                    // 其他consumer同时消费了该订阅下的相同shard,退出
                    bExit = true;
                    logger.error(" 其他consumer同时消费了该订阅下的相同shard,退出"+e.getMessage());
                    throw new Exception(e);
                }catch (InvalidCursorException ex) {
                    // 非法游标或游标已过期,建议重新定位后开始消费
                    // 针对于(the cursor is expired)
                    GetCursorResult cursorRs = client.getCursor(projectName, topicName, shardId, CursorType.LATEST);
                    cursor = cursorRs.getCursor();
    
                } catch (Exception e) {
                    bExit = true;
                    logger.error(" 异常退出"+e.getMessage());
                    throw new Exception(e);
                }
            }
    
        }

    产出数据文件代码

     /**
         * 写入txt文件
         *
         * @param result
         * @param fileName
         * @return
         */
        public static  boolean writeText(List<String> result, String fileName,String filePath)  {
            StringBuffer content = new StringBuffer();
            boolean flag = false;
            BufferedWriter out = null;
    
            try {
    
                if (result != null && !result.isEmpty() && StringUtils.isNotEmpty(fileName)) {
                    fileName += "_" + DateUtils.getCurrentTime_yyyyMMddHHmmssSSS() + ".txt";
    //                System.out.println("fileName>>>>>>>>>>>>>"+fileName);
                    File pathFile = new File(filePath);
                    if (!pathFile.exists()) {
                        pathFile.mkdir();
                    }
                    String relFilePath = null;
                    if(filePath.endsWith(File.separator)){
                        relFilePath = filePath + fileName;
                    }else{
                        relFilePath = filePath + File.separator + fileName;
                    }
    
                    File file = new File(relFilePath);
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "GBK"));
                    for (String info : result) {
    
                        out.write(info);
                        out.newLine();
                    }
                    flag = true;
                }
    
                if (out != null) {
                    try {
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                return flag;
            }
        }

    然后数据运行起来后就发现生成的文件里面的数据有些是不对的,有些行多几个字段,有些行少了几个字段。
    后来查了诸多资料,然后就知道了多个线程访问同一个方法时,为了保证数据的一致性,需要对共同访问的方法加同步锁,这个很重要!
    于是就把生成文件的代码修改了成了

     /**
         * 写入txt文件
         *
         * @param result
         * @param fileName
         * @return
         */
        public static synchronized boolean writeText(List<String> result, String fileName,String filePath)  {
            StringBuffer content = new StringBuffer();
            boolean flag = false;
            BufferedWriter out = null;
    
            try {
    
                if (result != null && !result.isEmpty() && StringUtils.isNotEmpty(fileName)) {
                    fileName += "_" + DateUtils.getCurrentTime_yyyyMMddHHmmssSSS() + ".txt";
    //                System.out.println("fileName>>>>>>>>>>>>>"+fileName);
                    File pathFile = new File(filePath);
                    if (!pathFile.exists()) {
                        pathFile.mkdir();
                    }
                    String relFilePath = null;
                    if(filePath.endsWith(File.separator)){
                        relFilePath = filePath + fileName;
                    }else{
                        relFilePath = filePath + File.separator + fileName;
                    }
    
                    File file = new File(relFilePath);
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "GBK"));
                    for (String info : result) {
    
                        out.write(info);
                        out.newLine();
                    }
                    flag = true;
                }
    
                if (out != null) {
                    try {
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                return flag;
            }
        }

    然后问题就解决了。

    展开全文
  • 首先请看一下如下的代码:设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。public class ThreadTest1{ private int j;...

    首先请看一下如下的代码:

    设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
    以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。
    public class ThreadTest1{
     private int j;
     public static void main(String[] args){
      ThreadTest1 tmp = new ThreadTest1();
      for(int i = 0;i < 2;i++ ){
       Thread t1 = new Thread(tmp.new Add());
       t1.run();
       Thread t2 = new Thread(tmp.new Delete());
       t2.start();
      }
     }
     
     private synchronized void add(){
      j ++;
      System.out.println(Thread.currentThread().getName() + ": " + j);
     }
     private synchronized void delete(){
      j --;
      System.out.println(Thread.currentThread().getName() + ": " + j);
     }
     
     class Add implements Runnable{
      public void run(){
       for(int i = 0;i < 5;i++ ){
        add();
       }
      }
     }
     class Delete implements Runnable{
      public void run(){
       for(int i = 0;i < 5;i++ ){
        delete();
       }
      }
     }
    }

    通过改动把t1.run()处该为t1.start(),比较两次运行的结果,你会发现两次运行的结果很不一样,下面是两次运行的结果:

    Thread-0: 1
    Thread-2: 2
    Thread-1: 1
    Thread-3: 0
    Thread-0: 1
    Thread-2: 2
    Thread-1: 1
    Thread-3: 0

     

    main: 1
    main: 2
    main: 3
    main: 4
    main: 5
    main: 6
    main: 7
    main: 8
    main: 9
    main: 10
    Thread-1: 9
    Thread-1: 8
    Thread-1: 7
    Thread-1: 6
    Thread-1: 5
    Thread-3: 4
    Thread-3: 3
    Thread-3: 2
    Thread-3: 1
    Thread-3: 0


    原因分析:

    start()方法:用来启动一个线程,这时此线程处于就绪状态,然后通过调用此线程的run()方法来完成线程的运行操作。

    run()方法:这只是一个方法,直接调用该方法只是把该方法的函数体给执行了一遍,并没真正启动一个线程,所以上面第二次运行的结果中会有main:线程

    展开全文
  • 线程调用: 1、动态库只有一个导出函数: 这种情况非常少,也是最容易处理的情况。这种情况下编写函数时,只需要考虑不要有冲突的全局数据就可以了。这里的全局数据包括了分配的数据块和静态全局变量等...
    多线程调用: 
    1、动态库只有一个导出函数:
    这种情况非常少,也是最容易处理的情况。这种情况下编写函数时,只需要考虑不要有冲突的全局数据就可以了。这里的全局数据包括了在堆中分配的数据块和静态全局变量等。如果存在这样的全局数据,那么进程中的不同线程访问这个函数就会造成冲突。
    解决办法也很简单,就是尽量用堆栈(stack)来解决问题。由于堆栈的所有人是线程,所以它必然是线程安全的。当然也要注意避免堆栈溢出。
    我们都知道,如果要在函数再次调用时保留前一次调用的状态,可以使用静态变量。但如果你要保持函数的线程安全,那么静态变量是不能用的,因为静态变量是全局的,是属于进程的,也就是属于进程内线程共享的。所以如果确实需要在同一线程中保持函数的状态,相当于在不同次调用间传递参数,可以考虑使用静态全局线程局部变量,即:
    __declspec( thread ) int tls_i = 1;
    该变量定义就使编译器保证了tls_i是对应于每个线程的,即每个线程都一个tls_i的副本(copy),这样必然就是线程安全的。
    2、动态库导出了多个函数,而且多个函数间存在数据传递。
    就像前面说的,一般DLL都导出多个函数,一个初始化,一个资源释放,其他为核心功能函数。这些函数间极有可能发生数据传递。如果一个初始化函数是在线程A中调用的,而核心功能函数是在线程B中调用的,那么线程A初始化函数的资源就无法对应线程B中的核心功能,此外还有核心功能函数间的数据传递,这样的DLL就不是线程安全的,必然导致错误。
    解决办法是由用户(即使用DLL的人)保证这些导出函数是在一个线程中调用。但这样会很大程度上限制接口的设计和用户的使用自由度。所以最好的方法是函数只管自己的线程安全,不同函数传递数据用动态TLS,线程局部存储。
    比如:
    我在全局定义了一个变量,用于存储当前线程局部存储的index ID。
    __declspec( thread ) int tls_i = 1;
    当调用分配资源的函数时,调用动态TLS函数TlsAlloc,分配一个ID,将其记录在全局的线程安全的tls_i变量,并通过TlsSetValue函数将数据保存在线程安全的区域;当调用获取资源的函数时,通过TlsGetValue获取资源,处理完成后,调用Tlsfree对TLS index释放,以便新线程占有。
    这样,只要DLL中每个函数保证其局部是线程安全的,函数间传递数据通过TLS(静态和动态),就可以实现整个DLL的线程安全。
    3、限制访问DLL中某一函数的线程数目。
    有时候,对于DLL中的某一个函数的访问线程数目是有限制的,超过了限制其他线程就得等一定的时间,一定的时间过后如果还不能得到执行机会,那就返回超时。这样的设计对用户来说是友好的,而且很实用,有的商业程序确实是按照允许用户访问的通道数目来计价的。
    对DLL中的函数做这样的一个封装,一般是简单的待用Semaphore信号量,来解决。DLL初始化时调用CreateSemaphore函数对信号量进行初始化,其原型如下:
    HANDLE CreateSemaphore(
    LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
    // pointer to security attributes
    LONG lInitialCount, // initial count
    LONG lMaximumCount, // maximum count
    LPCTSTR lpName // pointer to semaphore-object name
    );
    对于信号量,它每WaitForSingleObject一次(当然是要进入),其状态值(一个整数)就减1,使用完ReleaseSemaphore其状态值就加1,当其状态值为0时信号量就由有信号变为无信号。利用信号量的这一特性,我们在初始化时将信号量的初始值(第2个参数)设置为限制的线程访问数目。在要限制访问线程数目的函数内部,通过调用WaitForSingleOject获取控制权,并指定一个等待时间(这个由配置文件指定),根据情况超时返回,使用完ReleaseSemaphore释放对占用,让其他线程可以调用这个函数。
    4、多进程情况下的多线程安全DLL。
    前面3讲了有时候需要对某一函数的访问线程进行限制,而我们知道,DLL是可以被多个进行加载并调用的。那就是说如果我们只对一个进程进行了限制,那么在多进程调用的情况下,这样的限制被轻易攻破。
    我们都知道,Semaphore信号量属于内核对象,也就是说其可以被多进程共享访问,也就说,如果我们给一个Semaphore指定了一个名字,在另一个进程中,我们只要调用OpenSemaphore函数用同一名字打开信号量就可以访问了。这样问题就解决了?
    现实情况是,多进程情况下,一般不是简单的多进程共享一个Semaphore就可以了。多进程间需要互通很多信息。一般的解决办法是,采用共享数据段。
    #pragma data_seg("share")
    int share_data;
    #pragma data_seg()
    #pragma comment(linker,"/SECTION:share, RWS")
    通过pragam编译器指令生成了一个名叫share的共享数据段,这样对于变量share_data就可以多进程共享的了。如果要多进程间交换数据,只要在data_seg中添加数据定义即可。
    在MFC DLL中创建多线程:
    除了在初始化过程中,只要MFC DLL 使用 TlsAlloc 这样的 Win32 线程本地存储区 (TLS) 函数来分配线程本地存储区,就可以安全地创建多线程。但是,如果 MFC DLL 是使用 __declspec(thread) 分配线程本地存储区,客户端应用程序必须隐式链接到 DLL。如果客户端应用程序显式链接到 DLL,对 LoadLibrary 的调用将不会成功加载此 DLL。
    原因可以参考微软的这篇文章“PRB: Calling LoadLibrary() to Load a DLL That Has Static TLS”,地址:http://support.microsoft.com/kb/118816/en-us。
    启动期间创建新的 MFC 线程的 MFC DLL 在由应用程序加载时将挂起。每当在下列对象内部通过调用 AfxBeginThread 或 CWinThread::CreateThread 创建线程时,就会发生这种情况:

    规则 DLL 中 CWinApp 派生对象的 InitInstance。

    规则 DLL 中提供的 DllMain 或 RawDllMain 函数。

    扩展 DLL 中提供的 DllMain 或 RawDllMain 函数。
    为什么呢,原因可参考这篇文章“PRB: Cannot Create an MFC Thread During DLL Startup”,http://support.microsoft.com/kb/142243/en-us。

    解决办法:Regular DLLs that create threads should only do so in functions exported from the DLL and called by client applications.The recommended solution for MFC DLLs that need to create a thread when the DLL starts is to add a specific exported initialization function and create the thread in it.(创建多线程的规则dll,只能将启动线程的函数放入导出函数中,由客户端调用执行,不能在dll启动期间自动创建线程。)

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    文章转自:http://bbs.51cto.com/thread-513440-1.html

    展开全文
  • 同步方法调用一个同步方法的锁

    千次阅读 2016-10-15 20:45:06
    2 下列的叙述正确的是() public class Test2 { public static synchronized void main(String[] args) { Thread t = new Thread(){ public void run() { Sogou();

    2 下列的叙述正确的是()
    public class Test2 {
    public static synchronized void main(String[] args) {
    Thread t = new Thread(){
    public void run()
    {
    Sogou();
    }
    };
    t.run();
    //t.start();
    System.out.println(“Hello”);
    }
    static synchronized void Sogou()
    {
    System.out.println(“Sogou”);
    };
    }
    A HelloSogou
    B SogouHello
    C 不确定
    D hello
    注解:我觉得误区有两个:一个是run和start区别.Thread.run()是调用方法,Thread. start()是启动线程;另一个是锁持有问题。这个题是调用方法,和多线程就无关。本题只有一个线程,持有HelloSogou.class锁。那么,就是另一个问题:同步方法调用另一个同步方法的锁问题?
    public synchronized void methodA(int a, int b){}
    public synchronized void methodB(int a)
    {
    methodA(a, 0);
    }
    首先要明白两个问题,1.锁的对象是谁?2.谁持有了锁?
    假设方法A和B是在同一个类Test中的两个方法。
    Test t=new Test();
    t.methodB();
    调用methodB()方法,获得锁,锁是对象t;锁谁持有?当前线程(不可以说是methodB持有该锁),methodB又调用methodA,也需要锁t,该线程已持有t,当然可以直接调用methodA.类比到此题,只有一个主线程,调用main,持有HelloSogou.class锁,那当然可以直接调用Sogou方法。
    第二,如果是t.statrt(),那么这个题,静态同步函数的锁是该类的字节码文件.class。此题中,main函数和Sogou方法都是static的,所以持有相同锁 HelloSogou.class ,那么,在main线程(main 是一个线程也是一个进程 )中又开了一个线程.调用Sogou方法,锁会冲突。
    我的分析是:调用main函数(一个线程),main函数开启另一个线程,并启动,但是main函数和Sogou方法是同一个锁,所以main
    函数执行完毕后才会释放锁,Sogou方法才会执行,这就是为什么,换成start,是HelloSogou。
    第三,将Sogou方法的锁改为其他.class锁,那么,HelloSogou和SogouHello都可能出现。因为没有互斥现象了,变为抢占式.

    展开全文
  • Java停止线程执行的方法

    万次阅读 2015-06-27 15:51:29
    博客主页:http://blog.csdn.net/chszs、暂停或停止线程的理论Java编程,要暂停或停止当前正在运行的线程,有几种方法。对于把线程转入睡眠Sleep状态,使用Thread.sleep()是最正确的方式。或许有人会问,为...
  • 下列关于线程调度的叙述,错误的是()。 正确答案: B E 你的答案: A E F (错误) 调用线程的sleep()方法,可以使比当前线程优先级低的线程获得运行机会 调用线程的yeild()方法,只会使与当前...
  • 哪个方法可以任何时候被任何线程调用而不会产生预期的异常? ? A : notify() B : wait() C : notifyAll() D : sleep() E : yield() F : synchronized(this) 答案: ...
  • 终止线程的四种方法

    千次阅读 2013-04-06 15:08:55
    3. 同一个进程或另一个进程线程调用TerminateThread 函数(最好避免使用这种方法 )。 4. 该线程的主进程终止运行(避免使用 )。 下面将介绍终止线程运行的方法,并且说明线程终止运行
  • 位牛人的多线程和异步调用文章

    千次阅读 2012-12-09 22:35:05
    首先申明:这篇文章不是我写的,我看到的位牛人的,自己慢慢的消化了…… 摘要:本章讨论与智能客户端应用程序线程的使用有关的问题。为了最大限度地提高智能客户端...单线程执行系列应用程序指令,并且
  • 线程调用DBUS服务注意事项

    千次阅读 2008-09-26 21:38:00
    线程初始化,特别不要忘记调用dbus_g_thread_init。g_type_init();g_thread_init(NULL);dbus_g_thread_init();2.确保不同线程使用不同的DBusConnection。DBUS提供了函数dbus_bus_get_private用于获取独立的DBusC
  • C/C++线程退出的四种方法

    万次阅读 2019-02-14 22:52:32
    一个进程或另一个进程线程调用TerminateThread函数(应避免使用该方法)。 通过调用ExitThread函数,线程将自行撤消(最好不使用该方法)。 ExitProcess和TerminateProcess函数也可以用来终止线程的运行(应...
  • Android的UI控件都不是线程安全的,所以如果一个线程中直接更新主线程的UI控件时就会报如下错误: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a...
  • C# 5.0引入了async 和 await。这两关键字可以让你更方便的按照同步的方式写出异步代码。也就是说使你更方便的异步编程。下面演示使用async,await的方式:第步:将 VS2010 升级到 VS2010 sp1.第二步:下载...
  • Windows终止线程的四种方法

    千次阅读 2019-08-12 16:16:23
     • 同一个进程或另一个进程线程调用 TerminateThread 函数(应该避免使用这种方法)。  • 包含线程的进程终止运行(应该避免使用这种方法)。  下面将介绍终止线程运行的方法,并且说明...
  • 下列关于线程调度的叙述,错误的是()。 正确答案: B E 你的答案: A E F (错误) 调用线程的sleep()方法,可以使比当前线程优先级低的线程获得运行机会 调用线程的yeild()方法,只会使与当前...
  • C#线程)概述及常用方法

    千次阅读 多人点赞 2018-05-12 12:47:20
    入门线程小例子C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多...
  • android多线程之三:终止线程池的方法

    千次阅读 2017-09-03 22:21:47
    要了解如何线程池终止线程池,先来了解下线程池的几个方法: shutdown、awaitTermination、shutdownNow、isTerminated、isShutdownshutdown这个方法会平滑地关闭ExecutorService,当我们调用个方法时,...
  • Linux中线程使用详解

    万次阅读 2015-12-30 21:14:58
    Linux线程和进程的区别:http://blog.csdn.net/qq_21792169/article/details/50437304 ...线程退出的条件:下面任意一个都可以。...2.其他线程调用pthread_cancel取消该线程,且该线程可被取消。
  • Java多线程中的内存模型

    千次阅读 2017-05-14 19:35:19
    内存模型Java,所有实例域、静态域和数组元素都存储堆内存,堆内存在线程之间共享。局部变量(Local Variables),方法定义参数(Java语言规范称之为Formal Method Parameters)和异常处理器参数...
  • AndroidToast如何子线程中调用

    千次阅读 2016-11-08 16:06:08
    AndroidToast如何子线程中调用...从这个错误,我们可以看到, 是因为一个Looper对象的原因, 当然很多人是不看这个报错信息的,因为大部分android程序员都认为Toast是一个ui控件,需要主ui线程中操作才可以。。
  • 标准库提供一个API函数,这个函数以回调函数指针作为线程的执行代码并单独的线程中调用回调函数。问题是这样的线程不能创建执行对象成员函数的线程;只能使用普通的函数。因此,下列代码是失败的: // ...
  • 终止线程运行  若要终止线程的运行,可以使用下面的方法:  • 线程函数返回(最好使用这种方法)。  • 通过调用 ExitThread 函数,线程将自行撤消... • 同一个进程或另一个进程线程调用 TerminateThre
  • 线程

    千次阅读 2017-01-09 16:22:26
    传统操作系统,每个进程有一个地址空间和一个控制线程,这是进程的定义,经常存在在一个地址空间准并行运行多个控制线程的情形,这些线程像分离的进程。
  • VC如何创建一个新的线程

    千次阅读 2011-03-17 17:19:00
    // 开始一个线程,DialThread 为线程控制函数,头文件定义如下: static UINT DialThread(LPVOID pvThread); 随后在线程控制函数如此这般,调用线程实现函数 _Dial() UINT CRasThread::DialThread(LPVOID ...
  • 位牛人的多线程和异步调用文章 6.1 使用 Task 模式时的代码结构 首先申明:这篇文章不是我写的,我看到的位牛人的,自己慢慢的消化了…… 摘要:本章讨论与智能客户端应用程序线程的使用有关的问题。...
  • 首先申明:这篇文章不是我写的,我看到的位牛人的,自己慢慢的消化了…… 摘要:本章讨论与智能客户端应用程序线程的使用有关的问题。为了最大限度地提高智能客户端...单线程执行系列应用程序指令,并且
  • 操作系统作业:给linux系统增加一个系统调用

    万次阅读 多人点赞 2018-06-01 00:43:37
    前不久开了一门《操作系统》,老师上课留下了一个作业——给Linux系统添加一个系统调用。刚开始只能用一脸懵逼来形容,只能硬着头皮做下去。由于刚的新电脑,所以就没敢装双系统。所以我选择了虚拟机,虚拟机刚开始...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 70,432
精华内容 28,172
关键字:

在一个线程中调用下列方法