JAVA关于线程自己的一些理解

来源:互联网 发布:nginx iis 代理服务器 编辑:程序博客网 时间:2024/04/30 08:02

学生党,在之前开发android软件的时候不太了解线程,导致UI线程阻塞大哭所以特地回来学习下关于线程的知识,以下是我的总结


我理解线程的概念就是 各自、同时做一
些事情,达到一个目的,比如说:


我在吃饭的时候看电视,即在吃饭,又在看电视,吃饭是一个线程,看电视又是一个线程,同时发生.


概念也不想多讲,直接切入主题


Thread(线程)及相关信息 在 java.lang.*; 中.


线程的创建:

Thread thread=new Thread(Runnable r);

Thread构造函数必须要传递一个实现Runnable接口的实例,而实现Runnable接口必须要实现接口中的run()方法.


线程的启动与死亡:

thread.start();//线程启动

当此线程运行完成时线程死亡,注意死亡的线程不能再次start().


线程的创建、运行到死亡的流程:

线程创建 ———— 执行Runnable中的run()方法 ————  执行完毕线程死亡

package com.test;public class ThreadTest {//************************************main**************************************public static void main(String [] args){Thread thread=new Thread(new Runnable(){/*用于实现Runnable中的run方法的匿名内部类*/public void run(){System.out.println("Thread运行中");}});thread.start();}}
运行结果:
Thread运行中


如果说我们希望有个线程一直监控某个数据或者执行某项操作,需要通过 循环+Thread.sleep(long 休眠时间)来控制.

package com.test;public class ThreadTest {public static int apple=0;//************************************main**************************************public static void main(String [] args){Thread thread=new Thread(new Runnable(){/*这个是匿名内部类  用于实现Runnable中的run方法*/public void run(){while(true)//我这里用死循环{System.out.println(apple++);//控制台输出apple的值if(apple>10)break;try {Thread.sleep(1000);} //1000ms也是就1秒  子线程休眠一秒catch (InterruptedException e) {} //这里需要异常捕获}}});thread.start();}}
运行结果:

12345678910
每个输出都有一秒(不准确)的时间间距


多线程 join() 的作用:

如果在主线程中使用 t.join()  的话,那主线程只能等待,线程t执行完成后才能继续运行,比如说做饭,妈妈让你去买菜,真正开始做菜的话必须要等你买完菜回来.在这里:

将做饭看做是主线程,买菜看做子线程

Thread  买菜=new Thread(去买菜).start()

磨磨刀

洗洗菜板

买菜.join()

做饭.


<span style="font-size:18px;">package com.test;public class ThreadTest {public static int shopptime=0;//************************************main**************************************public static void main(String [] args){Thread thread=new Thread(new Runnable(){/*这个是匿名内部类  用于实现Runnable中的run方法*/public void run(){while(true)//我这里用死循环{System.out.println("正在买菜");if(shopptime++>5)break;try {Thread.sleep(1000);}//这里设置买菜时间为5秒catch (InterruptedException e) {} //这里需要异常捕获}}});thread.start();System.out.println("磨刀");System.out.println("洗菜板");try {thread.join();} catch (InterruptedException e) {}//异常捕获System.out.println("你小子才回来");System.out.println("做饭");}}</span> 

运行结果:

磨刀洗菜板正在买菜正在买菜正在买菜正在买菜正在买菜你小子才回来做饭

多线程并发控制:

synchronized锁机制,感觉有点类似数据库的排他锁,一个线程锁住某个对象或者是某个方法,只能自己独自使用直到锁解开其他线程才能使用,比如说: 上WC

package com.test;public class ThreadTest {//一个实现Runnable接口的类static class run1 implements Runnable{synchronized public void run(){for(int i=0;i<5;i++){String str=Thread.currentThread().getName();System.out.println(str+"在使用我!");}}}//************************************main**************************************public static void main(String [] args){run1 run=new run1();Thread t1=new Thread(run,"张三");//第二个参数为此线程的名字Thread t2=new Thread(run,"李四");t1.setPriority(10);//设置线程优先级,范围是整数的 1-10,数越大优先级越高,得到cpu资源时越先执行t2.setPriority(1);t1.start();t2.start();}}
运行结果:


张三在使用我!张三在使用我!张三在使用我!张三在使用我!张三在使用我!李四在使用我!李四在使用我!李四在使用我!李四在使用我!李四在使用我!

关于线程的基本使用只说到这里.

当程序频繁的先建线程启动时,如

package com.test;public class ThreadTest {static public run1 run;//一个实现Runnable接口的类static class run1 implements Runnable{public void run(){System.out.println("创建了一个线程");}}static public void Init(){new Thread(run).start();//新建线程并启动}//************************************main**************************************public static void main(String [] args){run=new run1();for(int i=0;i<10;i++){Init();//执行10次Init()函数}}}
运行结果:

创建了一个线程创建了一个线程创建了一个线程创建了一个线程创建了一个线程创建了一个线程创建了一个线程创建了一个线程创建了一个线程创建了一个线程

在上例中创建了10个新线程,做的都是同一件事,却多消耗了一些实现功能额外的内存:线程创建所耗时,线程回收耗时等等一系列时间,所以这里引入线程池的概念


线程池(ExecutorService)及相关信息在 java.util.concurrent.*  中

我把线程池看做是一个控制台,拥有一些线程,通过提交方法传递一个实现Runnable接口的实例过去,如果控制台中有可用的空闲线程,就直接运行实例,如果没有空闲的

线程,就会放入一个缓存队列中直到可以运行时再调出实例

目前我有了解的线程池类型:

SingleThreadExecutor

CachedThreadPool

FixedThreadPool

ScheduledThreadPool


线程池的创建:通过 Executors 的静态方法创建


线程池的提交方法:

execute(Runnable r);//传递实现Runnable接口的实例,return空

submit(Runnable r);//传递实现Runnable接口的实例,return任务执行结果


线程池的关闭:

shutdown();//当前线程所运行的实例不受影响,线程池不接受任何的实例,但会等到缓存队列中的实例全部运行完

shutdownNow();//会尝试终止当前线程所运行的实例,线程池不接受任何的实例,销毁与返回缓存队列

当线程池全部关闭时,线程池的状态会变为Terminated



1.SingleThreadExecutor  单例型线程池

顾名思义,依次执行传递过来的实例,每次执行完一个之后才执行下一个

ExecutorService es=Executors.newSingleThreadExecutor();//这里创建一个单例线程池


package com.test;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadTest {//一个实现Runnable接口的类static class run1 implements Runnable{private int number;//run所携带的数字public run1(int num){number=num;}public void run(){while(true)//死循环,使其永远不能执行完{System.out.println(number);}}}//************************************main**************************************public static void main(String [] args){ExecutorService es=Executors.newSingleThreadExecutor();//创建一个单例线程池es.execute(new run1(1));//第一个run1实例携带数字1es.execute(new run1(2));//第二个run1实例携带数字2<pre name="code" class="java">                es.shutdown();        }
}

运行结果:

11111…………无限1

2FixedThreadPool  复合型线程池

执行传递过来的实例,其中参数是最大可并行线程数

ExecutorService es=Executors.newFixedThreadPool(int);//这里创建一个复合型线程池

package com.test;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadTest {//一个实现Runnable接口的类static class run1 implements Runnable{private int number;//run所携带的数字public run1(int num){number=num;}public void run(){while(true)//死循环,使其永远不能执行完{System.out.println(number);}}}//************************************main**************************************public static void main(String [] args){ExecutorService es=Executors.newFixedThreadPool(2);//创建一个复合型线程池,同时执行2个线程es.execute(new run1(1));//第一个run1实例携带数字1es.execute(new run1(2));//第二个run1实例携带数字2                es.shutdown();        }}

运行结果:

1111…………222…………111…………



3 CachedThreadPool 缓存型线程池

执行传递过来的实例,最大可并行线程数基本等于无上限

ExecutorService es=Executors.newFixedThreadPool(int);//这里创建一个缓存型线程池

注意一点的是如果缓存型线程池发现有空闲线程在60(default)秒没有用到时,就会销毁该空闲线程

运行同上


注意的几点

SingleThreadExecutor 工作线程只有一个

FixedThreadPool 工作线程数为构造函数中传递的参数

CachedThreadPool 工作线程数不固定,当有空闲的工作线程时使用空闲的工作线程,没有的话创建一个新的工作线程,如果空闲的工作线程超过 60(default)秒没有工作,那么

该池子会自动销毁该线程

线程池不用了的话,使用shutdown()或shutdownNow()方法关闭释放资源


如果我想用一个规定了最大并行线程数的FixedThreadPool,要求其空闲的工作线程生存时间为30秒(虽然不知道有什么用),那么就要使用ThreadPoolExecutor类,他的使用方法与上面相同,只是构造方式不同,可直接通过构造函数实例

化对象:

ThreadPoolExecutor TPE=new ThreadPoolExecutor(corePoolSize,maximumPoolSize, keepAliveTime, unit,workQueue<p></p>);
第一个参数:池子的线程数

第二个参数:当池子线程均被占用,缓存队列已满,会创建新的线程来协助处理,如果当前线程数超过该参数,池子会采取拒绝策略(RejectExcutionHandler)

第三个参数:空闲线程生存时间

第四个参数:时间单位 TimeUnit

第五个参数:缓存队列,分为三种  ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue队列


例子:规定最大并行线程数为3的FixedThreadPoolm,其空闲线程存活时间为30秒


package com.test;import java.sql.Time;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.SynchronousQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ThreadTest {//一个实现Runnable接口的类static class run1 implements Runnable{private int number;//run所携带的数字public run1(int num){number=num;}public void run(){while(true)//死循环{System.out.println(number);try {Thread.sleep(1000);} //休眠1秒catch (InterruptedException e) {}}}}//************************************main**************************************public static void main(String [] args){ThreadPoolExecutor TPE=new ThreadPoolExecutor(3,3,30L,TimeUnit.SECONDS,//事件单位秒new LinkedBlockingQueue<Runnable>());TPE.execute(new run1(1));//第一个run1实例携带数字1TPE.execute(new run1(2));//第二个run1实例携带数字2TPE.execute(new run1(3));//第三个run1实例携带数字3TPE.execute(new run1(4));//第四个run1实例携带数字4}}

运行结果:


123321123213312………………


4 ScheduledThreadPool  延迟型线程池

延时执行传递过来的实例,其中参数是最大可并行线程数

ScheduledExecutorService SES=Executors.newScheduledThreadPool(int)//创建一个延迟线程池

注意类名不再是ExecutorSevice,而是ScheduledExecutorService

传递实例的方法也变为 schedule(Runnable,int(延时执行),int(时间单位));


package com.test;import java.sql.Time;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.SynchronousQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ThreadTest {//一个实现Runnable接口的类static class run1 implements Runnable{private int number;//run所携带的数字private int time;//记录运行次数public run1(int num){number=num;time=0;}public void run(){while(time<10)//执行10次的循环{System.out.println(number+"运行时间:"+time++);try {Thread.sleep(1000);} //休眠1秒,则time近似于执行时间catch (InterruptedException e) {}}}}//************************************main**************************************public static void main(String [] args){ScheduledExecutorService SES=Executors.newScheduledThreadPool(3);SES.schedule(new run1(1),0,TimeUnit.SECONDS);//第一个线程携带数字1,延迟0秒执行,时间单位为秒SES.schedule(new run1(2),2,TimeUnit.SECONDS);//第二个线程携带数字2,延迟2秒执行,时间单位为秒SES.schedule(new run1(3),6,TimeUnit.SECONDS);//第三个线程携带数字3,延迟6秒执行,时间单位为秒SES.schedule(new run1(4),0,TimeUnit.SECONDS);//第四个线程携带数字4,延迟0秒执行,时间单位为秒}}
运行结果:


4运行时间:01运行时间:04运行时间:11运行时间:14运行时间:21运行时间:22运行时间:01运行时间:34运行时间:32运行时间:11运行时间:44运行时间:42运行时间:21运行时间:54运行时间:52运行时间:31运行时间:64运行时间:62运行时间:44运行时间:71运行时间:72运行时间:54运行时间:81运行时间:82运行时间:64运行时间:91运行时间:92运行时间:73运行时间:02运行时间:83运行时间:12运行时间:93运行时间:23运行时间:33运行时间:43运行时间:53运行时间:63运行时间:73运行时间:83运行时间:9



0 0