很多时候在处理一些耗时操作时,需要通过开辟线程来处理,这样不会阻塞主线程的执行。
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)
运行结果: