线程创建汇总——JAVA/C/C++

本文详细介绍了在Java、C、C++及Android中如何创建和管理线程,包括线程的创建过程、线程间同步机制以及线程调度的基本原理。特别强调了在多线程环境下使用锁和条件变量的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很多时候在处理一些耗时操作时,需要通过开辟线程来处理,这样不会阻塞主线程的执行。

1、JAVA的线程创建。

2、C中的创建线程,编译需要加线程参数,如:gcc cthread.c -o cthread -lpthread

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *test_print(void *arg)//线程创建成功后会执行这个方法
{
    int i;
    for ( i = 0; i < 10; i++)
    {
         printf("cthread: test_print start--->i =  %d\n", i);
    }
    
    return arg;
}

int main()
{
    pthread_t main_tid;
	int err = pthread_create(&main_tid, NULL, test_print, NULL); //创建线程
    if(err < 0)
    {
        printf("cthread: pthread_create-->error\n");
        return -1;
    }
    //不会等test_print方法执行完,因为main方法跟test_print方法不在同一个线程
    printf("cthread:it's main process.\n");
    sleep(2);
    
    return 0;
}

运行结果:

3、C++中的线程创建,这里是C++11的里面的thread,编译需要加-std=c++11,如: g++ -std=c++11 cppthread.cpp -o cppthread -lpthread

#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>
#include <unistd.h>
#include <mutex>

/*mutex是用来保证线程同步的,防止不同的线程同时操作同一个共享数据。
使用lock_guard则相对安全,它是基于作用域的,能够自解锁,当该对象创建时,
它会像m.lock()一样获得互斥锁,当生命周期结束时,它会自动析构(unlock),
不会因为某个线程异常退出而影响其他线程*/
std::mutex m;

void f1(int n)
{
    std::lock_guard<std::mutex> lockGuard(m);
    for (int i = 0; i < 7; ++i) {
        std::cout << "f1-->Thread " << n++ << " executing\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    std::cout << "由于t1线程加锁了,所以t2线程会等待t1执行结束" << std::endl;
}

void f2(int& r)
{
    std::lock_guard<std::mutex> lockGuard(m);
    for (int i = 0; i < 5; ++i) {
        std::cout << "f2-->Thread " << r++ << " executing\n";
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int main()
{
    std::cout<< std::endl;
    std::cout << "main函数开始执行" << std::endl;
    int n = 0, r = 0;
    std::thread t1(f1, n); //pass by value
    std::thread t2(f2, std::ref(r)); //pass by reference
    /*join:调用该函数会阻塞当前线程。阻塞调用者(caller)所在的线程直至被join的std::thread对象标识
    的线程执行结,必须将线程join或者detach 等待子线程结束主进程才可以退出 */
    t1.join();//等待t1退出
    t2.join();//等待t2退出
    //n值不会改变,因为是传值
    std::cout << "Final value of n is " << n << '\n';
    //r值会变化,因为传的是引用,参数是引用跟指针都是修改参数指向的对象
    std::cout << "Final value of r is " << r << '\n';
    std::cout << "main函数执行结束" << std::endl;
    std::cout<< std::endl;
}

运行结果如下:

如果不进行加锁,f1跟f2函数的执行是随机的,没有先后顺序,因为线程的调度是系统完成的。注销加锁代码,运行结果如下:

从打印结果上看,不加锁,f1跟f2函数随机执行。

4、Android中封装后的线程实现,直接上代码,头文件SendThread.h

#ifndef MCUCONTROLLER_H_
#define MCUCONTROLLER_H_
#include <utils/threads.h>
using namespace android;

class SendThread :public Thread{
public:
    virtual bool threadLoop() ;
    void  block();
    void unblock();
	Condition  mCondition;
	Mutex  mConditionMutex;

};

#endif

函数体SendThread.cpp

#include <stdio.h>
#include <unistd.h>
#include "SendThread.h"

pthread_mutex_t clifd_mutex = PTHREAD_MUTEX_INITIALIZER;

/**
 * 阻塞当前线程
 */
void SendThread::block() {
    printf("SendThread::block------>\n");
    pthread_mutex_lock(&clifd_mutex);
}

/**
 * 唤醒当前线程
 */
void SendThread::unblock() {
    printf("SendThread::unblock------>\n");
    pthread_mutex_unlock(&clifd_mutex);
}

/**
 * 发送数据的线程队列
 */
bool SendThread::threadLoop() {
    printf("SendThread::threadLoop--->\n\n");
    int i = 0;
    while (1)
    {
        if (i > 10)
        {
            break;
        }
        printf("SendThread::threadLoop--->before send data---->\n");
        block();
        i++;
        printf("SendThread::threadLoop--->send data = %d\n", i);
        sleep(1);
    }

    return false;//如果返回的true,threadLoop方法会被重复执行
}

测试代码:

#include <stdio.h>
#include "SendThread.h"

int main()
{
    printf("main --->start--->\n");
    sp<SendThread> mSendThread;
    mSendThread = new SendThread;
    mSendThread->run("sendThread");
    int i;
    for (i = 1; i < 5; i++)
    {
        /* code */
        sleep(1);
        printf("main --->thread unblock\n");       
        mSendThread->unblock();//解除锁,才会进行SendThread::threadLoop--->send data打印
        printf("main --->i = %d\n\n", i);
    }
    
    return 0;
}

android源码中编译需要添加Android.mk文件

# Copyright (C) 2012 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
	thread_main.cpp \
	SendThread.cpp \
#LOCAL_LDLIBS    := -llog	
LOCAL_SHARED_LIBRARIES :=   libutils \
			  libcutils \
			  libbase      		           
LOCAL_MODULE := thread_main
LOCAL_CFLAGS += -Wall
LOCAL_MODULE_TAGS := eng
include $(BUILD_EXECUTABLE)

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值