多线程

来源:互联网 发布:java web 插件式开发 编辑:程序博客网 时间:2024/05/16 11:05

1.创建线程的第一种方法

package day07;/** * 线程 * 线程可以并发运行多段代码。 *  * 创建线程有两种方式 * 方式一:继承Thread,重写run方法 * run方法中的代码就是需要让线程并发执行的代码(任务) * @author soft01 * */public class ThreadDemo1 {public static void main(String[] args) {Thread t1 = new MyThread1();Thread t2 = new MyThread2();/* * 启动线程要调用线程的start方法,而不是直接调用run方法! * start方法调用完毕后,run方法会很快的被调用。 */t1.start();t2.start();}}/** * 第一种创建线程的方式有两个不足 * 1:继承冲突 * 由于java是单继承的,这就导致若继承了Thread当前类 * 就无法继承其它类来复用方法,这在实际开发中是非常不方法的。 * 2:由于在当前类内部重写run方法,这就导致当前线程与该线程 * 要执行的任务有一个必然的耦合关系,不利于线程复用。 * @author soft01 * */class MyThread1 extends Thread{public void run() {for(int i=0;i<1000;i++) {System.out.println("你是谁啊?");}}}class MyThread2 extends Thread{public void run() {for(int i=0;i<1000;i++) {System.out.println("我是查水表的!");}}}

2.创建线程的第二种方法

package day07;/** * 第二种创建线程的方式: * 实现Runnable接口并重写run方法来单独定义线程任务 * @author soft01 * */public class ThreadDemo2 {public static void main(String[] args) {/* * 创建线程要执行任务 */Runnable r1 = new MyRunnable1();Runnable r2 = new MyRunnable2();/* * 创建线程 */Thread t1 = new Thread(r1);Thread t2 = new Thread(r2);t1.start();t2.start();}}class MyRunnable1 implements Runnable{public void run() {for(int i=0;i<1000;i++) {System.out.println("你是谁啊?");}}}class MyRunnable2 implements Runnable{public void run() {for(int i=0;i<1000;i++) {System.out.println("我是查水表的!");}}}

3.使用匿名内部类完成两种方式线程的创建

package day07;/** * 使用匿名内部类完成两种方式线程的创建 * @author soft01 * */public class ThreadDemo3 {public static void main(String[] args) {/* * 使用匿名内部类完成方式一创建线程 */Thread t1 = new Thread (){public void run() {for(int i=0;i<1000;i++) {System.out.println("你是谁啊?");}}};/* * 使用匿名内部类完成方式二创建Runnable */Runnable r2 = new Runnable() {public void run() {for(int i=0;i<1000;i++) {System.out.println("我是查水表的!");}}};Thread t2 = new Thread(r2);t1.start();t2.start();}}

4.获取线程相关信息的方法

package day07;/** * 获取线程相关信息的方法 * @author soft01 * */public class Thread_info {public static void main(String[] args) {Thread t1 = new Thread() {public void run() {System.out.println("自定义线程t1执行了!");//获取线程ID id:唯一标识long id = this.getId();System.out.println("t1的ID:"+id);//获取名字Thread-xxString name = this.getName();System.out.println("t1的名字:"+name);//获取线程优先级 1-10int priority = this.getPriority();System.out.println("t1的优先级:"+priority);//查看当前线程是否为守护线程boolean isDaemon = this.isDaemon();System.out.println("t1是否为守护线程"+isDaemon);//查看线程是否处于活动状态boolean isAlive = this.isAlive();System.out.println("t1是否活着:"+isAlive);//查看线程是否被中断boolean isInterrupted = this.isInterrupted();System.out.println("t1是否被中断了"+isInterrupted);}};t1.start();}/*结果如下:自定义线程t1执行了!t1的ID:9t1的名字:Thread-0t1的优先级:5t1是否为守护线程falset1是否活着:truet1是否被中断了false*/}

5. 线程提供了一个静态方法:static Thread currentThread()

package day07;/** * 线程提供了一个静态方法 * static Thread currentThread() * 该方法可以获取运行该方法的线程 * @author soft01 * */public class Thread_currentThread {public static void main(String[] args) {/* * 获取运行main方法的线程 */Thread main = Thread.currentThread();System.out.println("运行main方法的线程是:"+main);dosome();//main线程执行dosome方法//自定义线程Thread t = new Thread() {public void run() {Thread t = Thread.currentThread();System.out.println("自定义线程:"+t);dosome();}};t.start();}public static void dosome() {Thread t = Thread.currentThread();System.out.println("运行dosome方法的线程是:"+t);}/*结果如下:运行main方法的线程是:Thread[main,5,main]运行dosome方法的线程是:Thread[main,5,main]自定义线程:Thread[Thread-0,5,main]运行dosome方法的线程是:Thread[Thread-0,5,main]*/}

6.线程优先级

package day07;/** * 线程优先级 *  * 线程不能干涉线程调度的工作,即:线程不能主动获取CPU事件片。 *  * 为了最大程度的改善某个线程获取CPU时间片的次数, * 可以通过调整线程优先级来完成。 * 理论上线程优先级越高的线程获取CPU时间片的次数越多。 *  * 线程的优先级有10个等级,分别用整数1-10表示。 * 1最低,10最高,5为默认值。 * @author soft01 * */public class Thread_priority {public static void main(String[] args) {Thread max =new Thread() {public void run() {for(int i=0;i<10000;i++) {System.out.println("max");}}};Thread min =new Thread() {public void run() {for(int i=0;i<10000;i++) {System.out.println("min");}}};Thread nor =new Thread() {public void run() {for(int i=0;i<10000;i++) {System.out.println("nor");}}};max.setPriority(Thread.MAX_PRIORITY);min.setPriority(Thread.MIN_PRIORITY);min.start();nor.start();max.start();}}

7.Thread提供了一个静态方法:static void sleep(long ms)

package day07;/** * Thread提供了一个静态方法: * static void sleep(long ms) * 该方法可以将运行该方法的线程阻塞指定毫秒, * 当超时以后该线程会自动回到RUNNABLE状态等待再次并发运行。 *  * 常使用该方法做间隔时间等操作使用 * @author soft01 * */public class Thread_sleep {public static void main(String[] args) {System.out.println("main方法执行了");try {Thread.sleep(5000);}catch(InterruptedException e) {e.printStackTrace();}System.out.println("main方法结束了");}}

8. 输入一个数字,从该数字开始倒数,直到0为止。

package day07;/** * 输入一个数字,从该数字开始倒数,直到0为止。 * 每个一秒倒数一次 * @author soft01 * */import java.util.Scanner;public class Test {public static void main(String[] args) {Thread t =new Thread() {Scanner scan = new Scanner(System.in);int num = Integer.parseInt(scan.next());public void run() {for(int i=num;i>=0;i--) {System.out.println(i);try {Thread.sleep(1000);}catch(InterruptedException e) {e.printStackTrace();}}}};t.start();}}

9.守护线程:跟前台线程结束不同,前台进程都结束,后台进程(守护线程)强制结束。

package day07;/** * 守护线程 * 守护线程又称为后天线程。默认创建出来的线程都是前台线程。 * 使用上守护线程与前台线程没有区别没有区别, * 而区别在于结束实际上有一点不同,即:进程结束。 * 当一个进程中的所有前台线程都结束时,进程结束, * 无论该进程中的守护线程是否还在运行都要强制将它们结束。 * @author soft01 * */public class Thread_setDaemon {public static void main(String[] args) {Thread rose = new Thread() {public void run() {for(int i=0;i<5;i++) {System.out.println("rose:let me go!");try {Thread.sleep(1000);}catch(InterruptedException e) {}}System.out.println("rose:aaaaAAAAA");System.out.println("扑通!");}};Thread jack = new Thread() {public void run() {while(true) {System.out.println("jack:you jump!i jump!");try {Thread.sleep(1000);}catch(InterruptedException e) {}}}};//设置为守护线程,必须在线程启动之前设置。jack.setDaemon(true);rose.start();jack.start();}}

10.线程提供了一个方法:join,该方法可以协调多个线程之间同步运行。

package day07;/** * 线程提供了一个方法:join * 该方法可以协调多个线程之间同步运行。 *  * 同步与异步 * 所谓同步执行指的的执行有先后顺序。 * 异步执行则执行没有顺序,各干各的。 *  * 多线程运行本身的设计是异步运行的, * 但在某些业务逻辑中需要他们执行各自任务时要有先后, * 这时就需要协调这些线程之间同步运行。 * @author soft01 * */public class Thread_join {//表示图片是否下载完毕private static boolean isFinish = false;public static void main(String[] args) {/* * JDK8之前,由于JVM内存设计问题,有一个要求: * 当一个方法的局部内部类中要使用这个方法的其他局部变量时, * 该变量必须是final的。 */final Thread download = new Thread() {public void run() {System.out.println("down:开始下载图片...");for(int i=1;i<=100;i++) {System.out.println("down:"+i+"%");try {Thread.sleep(50);}catch(InterruptedException e) {}}System.out.println("down:图片下载完毕!");isFinish = true;}};Thread show = new Thread() {public void run() {System.out.println("show:开始显示图片...");/*等待下载线程将图片下载完毕... *  * 当show线程调用download的join方法时, * show线程处于阻塞状态,直到download线程将任务全部执行完毕后, * show才会结束阻塞继续执行join方法后续代码。 */try {download.join();//等待图片加载完毕}catch(InterruptedException e) {e.printStackTrace();}if(!isFinish) {/* * 将一个异常抛出到该线程的run方法之外意味着该线程就结束了 */throw new RuntimeException("图片没有下载完成!");}System.out.println("show:图片显示完毕!");}};download.start();show.start();}}


11.线程池:重用线程,控制线程数量

package day7;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * 线程池 * 频繁的创建销毁线程,或者创建过多的线程都会给系统 * 带来风险。轻者拖慢系统,出现卡顿现象,严重时可能出现 * 内存溢出系统瘫痪。 * 为此,我们在处理并发量大的业务逻辑时,常常使用线程池 * 来管理和调度线程。 *  * 线程池主要解决两个问题: * 1:重用线程(避免频繁创建销毁线程) * 2:控制线程数量(避免因为大量的线程导致的系统崩溃) * @author soft01 * */public class ThreadPoolDemo {public static void main(String[] args) {ExecutorService threadPool = Executors.newFixedThreadPool(2);for(int i=0;i<5;i++) {Runnable runn = new Runnable() {public void run() {Thread t = Thread.currentThread();try {System.out.println(t.getName());Thread.sleep(5000);System.out.println(t.getName());}catch(InterruptedException e) {System.out.println(t.getName()+"被中断了!");}}};threadPool.execute(runn);System.out.println("将任务交给了线程池");}//循环结束//threadPool.shutdownNow();//System.out.println("线程池停止了");}}