Java中的多线程
首先,我们需要明白在Java中,多线程就是一个类或者一个程序执行或者管理多个线程执行任务的能力,线程总是处于5种状态之中,分别是:创建,可运行,运行中,阻塞,死亡。
创建:使用 new 运算符后,该线程仅仅是一个空对象,系统没有分配资源,该线程处于创建状态(new thread)
可运行:使用start()方法启动一个线程后,系统为该线程分配了除了CPU外的所需资源,该线程处于可运行状态(Runnable)
运行:Java运行系统通过调度选中其中一个Runnable的线程,使其占有CPU并转为运行中状态(Running)时。系统真正执行线程的run()方法。
阻塞:一个正在运行的线程因某种原因无法继续运行时,进入阻塞状态(Blocked)
死亡:线程结束后是死亡状态(Dead)
在java中进程分成普通线程和守护线程,区别在于结束的方式,普通线程和守护线程可以以并行的方式执行,但是当所有的普通线程都结束时,守护线程也会相应停止。可以使用**setDeamon(boolean)**方法来将普通线程变成守护进程
join()函数:thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
##########################################################################################
接下来,我将通过实例来进一步细说线程及相关知识
通过继承Thread创建一个线程
主要包含两个类,HelloMain.java和HelloThread.java,其中HelloThread类继承了Thread类并重写了它的run()方法,HelloMain中启动HelloThread。
HelloMain.java
package com.caigentan.java.thread;
public class HelloMain {
public static void main(String[] args) throws InterruptedException{
int idx = 1;
for(int i=0;i<2;i++){
System.out.println("Main thread running " + idx++);
Thread.sleep(2101);
}
HelloThread helloThread = new HelloThread();
helloThread.start();
for (int i = 0; i < 3; i++){
System.out.println("Main Thread running " + idx++);
Thread.sleep(2101);
}
System.out.println("=====> Main thread stopped");
}
}
HelloThread.java
package com.caigentan.java.thread;
public class HelloThread extends Thread{
@Override
public void run() {
int index = 1;
for(int i = 0;i<10;i++){
System.out.println(" - HelloThread Running" + index++);
try {
Thread.sleep(1030);
}catch (InterruptedException e){
}
}
System.out.println("====> HelloThread stopped");
}
}
运行效果如下:
守护进程
java中进程分成普通线程和守护线程,区别在于结束的方式,普通线程和守护线程可以以并行的方式执行,但是当所有的普通线程都结束时,守护线程也会相应停止。可以使用**setDeamon(boolean)**方法来将普通线程变成守护进程。
此处的实验分成3个,分别是DeamonTest.java,DeamonThread.java和NoDeamonThread.java
DeamonTest.java
package com.caigentan.java.thread.deamon;
public class DeamonTest{
public static void main(String[] args) {
System.out.println("\nMain Thread Start.. \n");
Thread deamonThread = new DeamonThread();
deamonThread.setDaemon(true);
deamonThread.start();
new NoDeamonThread().start();
try{
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("\nMain Thread end..\n");
}
}
DeamonThread.java
package com.caigentan.java.thread.deamon;
public class DeamonThread extends Thread{
@Override
public void run() {
int count = 0;
while(count<100){
System.out.println("Hello From DeamonThread" + count++);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("DeamonThread end..");
}
}
NoDeamonThread.java
package com.caigentan.java.thread.deamon;
public class NoDeamonThread extends Thread{
@Override
public void run() {
int i = 0;
while(i<10){
System.out.println(" -Hello From NoDeamon Thread" + i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("\n====> NoDeamon Thread ending\n");
}
}
效果如下,可以看到,当程序中所有的普通进程都停止时,守护进程也会立即停止。在java中守护进程的典型例子就是GC机制,当所有程序都停止,GC机制也会自动停止
线程池
线程池是管理线程的高级技术,通常它提供了如下几个功能
●通过对线程的管理,更加合理的调配资源。通常,线程池里维护着一组空闲线程,并向外 提供,根据系统繁忙程度动态増加或减少空闲线程的数量。比较高级的还提供了自动检测 异常线程的功能
●通过维护池中即存线程,可以节省创建线程的开销,尤其是对于 Web server这类处理频繁 而处理过程又比较快的程序,创建线程的开销是不能忽略的。
此处使用两个程序进行说明,普通线程ExecutorServiceDemo1.java 和调用类ExecutorServiceThread.java。
ExecutorServiceDemo1.java
package com.caigentan.java.thread;
public class ExecutorServiceDemo1 extends Thread{
private String threadName;
private int count;
public ExecutorServiceDemo1(String threadName, int count){
this.threadName = threadName;
this.count = count;
}
@Override
public void run() {
int i = 0;
while(i<count){
System.out.println("thread " + this.threadName + " start! " + i++);
try {
Thread.sleep(1024);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
ExecutorServiceThread.java
package com.caigentan.java.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceThread {
public static void main(String[] args) {
System.out.println("Main thread starting...");
//创建线程池
ExecutorService exec = Executors.newFixedThreadPool(3);
ExecutorServiceDemo1 hello1 = new ExecutorServiceDemo1("hello1",2);
ExecutorServiceDemo1 hello2 = new ExecutorServiceDemo1("hello2",2);
ExecutorServiceDemo1 hello3 = new ExecutorServiceDemo1("hello3",2);
while (true) {
exec.execute(hello1);
exec.execute(hello2);
exec.execute(hello3);
try {
Thread.sleep(2030);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
当 ExecutorService exec = Executors.newFixedThreadPool(3);
可以看到每次可以同时运行3个线程
当 ExecutorService exec = Executors.newFixedThreadPool(2);
可见每次只能同时运行2个线程
join()
join()表示运行在当前运行的线程中插入另外一个线程,并且在插入的线程运行结束前不会运行下面的线程。
此处使用2个文件来说明,分别是JoinTest.java和JoinThread.java
JoinTest.java
package com.caigentan.java.thread.join;
public class JoinTest {
public static void main(String[] args) throws InterruptedException {
System.out.println("\n==> Main thread starting..\n");
Thread joinThreadA = new JoinThread("joinThreadA",2);
Thread joinThreadB = new JoinThread("joinThreadB",3);
Thread noJoinThreadC = new JoinThread("joinThreadC",5);
// noJoinThreadC.setDaemon(true);
joinThreadA.start();
joinThreadB.start();
noJoinThreadC.start();
joinThreadA.join();
joinThreadB.join();
System.out.println("Hello from main thread...");
System.out.println("Thread A isLive? " + joinThreadA.isAlive());
System.out.println("Thread B isLive? " + joinThreadB.isAlive());
System.out.println("Thread C isLive? " + noJoinThreadC.isAlive());
System.out.println("\n==> Main Thread end!\n");
}
}
JoinThread.java
package com.caigentan.java.thread.join;
public class JoinThread extends Thread{
private String threadName;
private int count;
public JoinThread(String threadName,int count){
this.threadName = threadName;
this.count = count;
}
@Override
public void run() {
for (int i=1;i<count;i++){
System.out.println("Hello From " + this.threadName + " " + i);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("===>Thread " + threadName + " end\n");
}
}
效果如下:
关于常用的多线程目前就到此,还有一些高级使用代日后使用到了我再来更新!