java使用多线程
进程与线程
线程又称轻量级进程,是程序执行的最小单元,一个进程最少有一个线程,线程间通信比进程间通信更有优势,多个线程在一个进程中可以方便数据共享.注意线程的异常可能引起程序(进程)的崩溃.线程虽然称轻量级进程,那只是对比进程来说,但开销还是很大的,要正确合理使用线程,一定要避免线程太多,造成线程上下文开销很大,从而影响程序的性能.
Windows系统多线程优于Unix/Linux,以多进程来说Unix/Linux比Windows有优势.
Java的跨平台是以针对不同平台(Windows/Linux/Macos)的虚拟机(JVM),屏蔽不同平台的差异.线程在JVM中没有直接实现而是调用不用平台的系统API创建的.Java中的一个线程对应了系统的一个线程.
线程的状态
线程的状态分别为:新生→就绪→运行/等待→死亡,一般我们只考虑就绪/等待/运行,可以看看下图.

如何使用系统API创建线程
在Windows系统使用系统API创建
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h> //CreateThread函数原型在Windows头文件
//回调函数
DWORD WINAPI func(void* p)
{
printf("func exec is ok!\n");
return 0;
}
//在Windows系统,创建线程要使用CreateThread
int main(int argc, char *argv[])
{
//将func函数交给CreateThread API函数,创建完线程,执行func函数
HANDLE thread = CreateThread(NULL,0,func,NULL,0,NULL);
system("pause"); //暂停,比如新建的线程还没有执行,主线程已经运行结束,进程也就结束了
CloseHandle(thread);
return 0;
}
在Linux系统使用API创建线程
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//回调函数
void *func(void *args)
{
printf("func exec is ok!\n");
}
//在Linux/unix中,使用pthread_create创建线程
int main(int argc, char *argv[])
{
pthread_t pid;
pthread_create(&pid, NULL, func, NULL);
getchar(); //pause在Linux下不会阻塞等待,可以使用getchar或者fgetc
return 0;
}
为什么要使用系统API创建线程呢?
熟悉不同平台的API,了解不同平台的差异,能够让我们知其所以然,知道了这些,就可以说Java的线程使用.Java两种实现多线程的方式
1.继承Thread
public class MyThread extends Thread {
public MyThread(String name) {
setName(name);
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
/*
* 多线程,要注意是执行是乱序的,当然也有可能是顺序的.
* 1.让类继承Thread,重写run方法
* 2.让类实现Runnable接口,重写run方法
* 推荐使用使用Runnable接口,因为类只能单继承,而接口可以多实现
*/
public static void main(String[] args) {
System.out.println("main thread id:" + Thread.currentThread().getName());
System.out.println("=====================");
new MyThread("mythread1").start();
new MyThread("mythread2").start();
}
2. 实现Runnable接口
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
/*
* 多线程,要注意是执行是乱序的,当然也有可能是顺序的.
* 1.让类继承Thread,重写run方法.
* 2.让类实现Runnable接口,重写run方法.
* 推荐使用使用Runnable接口,因为类只能单继承,而接口可以多实现
*/
public static void main(String[] args) {
System.out.println("main thread id:" + Thread.currentThread().getName());
System.out.println("=====================");
MyRunnable run1 = new MyRunnable();
new Thread(run1, "myrun1").start();
new Thread(run1, "myrun2").start();
}
看一下Thread源码
Thread类是精简过的,旨在了解上面说的2种方式多线程方式.//Thread类也实现Runable接口
public class Thread implements Runnable {
private Runnable target;
public Thread() {
init(null, null, "Thread-", 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, null, true);
}
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
/*
* 初始化线程的信息,如线程
*/
}
private native void start0();
public synchronized void start() {
start0(); // 调用native函数start0,start0内部调用run函数
}
@Override
public void run() {
if (target != null) { // 如果继承Thread或实现Runable接口类不为空,变要调用该类重写的run方法
target.run();
}
}
}
秋风
2017-06-30