1.线程的创建方式
1.继承Thread并重写run方法,run方法是用来定义当前线程
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(); } } /* * 继承线程重写run方法这样的做法有两个不足: * 1.由于java是单继承,这就导致继承了Thread就不能继承 * 其他类。 * 2.由于重写run方法将线程的任务定义在了线程当中,这就 * 导致线程的重用性变得很差。线程与任务不应有必然的耦合关系。 */ 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.实现Runable接口单独定义线程任务
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.使用匿名内部类来完成两种方式的线程创建
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("你是谁啊"); } } }; Thread t2 = new Thread(new Runnable(){ public void run(){ for(int i = 0;i<1000;i++){ System.out.println("我是你爸爸"); } } }); t1.start(); t2.start(); } }
2.线程的优先级
/** * 线程优先级 * * 线程对线程调度的工作是不可控的,即: * 线程只能被动被分配CPU时间,而不能主动获取到。 * * 线程调度会尽可能的将CPU时间分配的几率做到均匀。但是 * 多个线程开发运行,并不保证一个线程一次这样交替运行。 * * 可以通过调整线程的优先级改善分配CPU时间片几率。 * 理论上线程优先级越高的线程,获取CPU时间片的次数就多。 * * 线程的优先级有10级,分别用整数1-10表示 * 其中1最低,5默认,10最高 * @author tarena * */ public class Thread_setPriorty { 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 mor = new Thread(){ public void run (){ for(int i=0;i<10000;i++){ System.out.println("mor"); } } }; Thread min = new Thread(){ public void run(){ for(int i = 0;i<10000;i++){ System.out.println("min"); } } }; //改变线程的优先级 max.setPriority(Thread.MAX_PRIORITY); min.setPriority(Thread.MIN_PRIORITY); min.start(); mor.start(); max.start(); } }
3.守护线程的使用
/** * 守护线程,又称为:后台线程 * 使用上与前台线程并无区别,所有线程默认创建出来都是 * 前台线程,想变为守护线程需要单独设置。 * * 但是结束时机上有一点不同: * 当进程结束时,所有正在运行的守护线程都会被强制结束。 * 而一个进程中所有前台线程都结束,进程就会结束。 * @author tarena * */ public class Thread_setDemo { 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);//使线程进入阻塞状态 每隔一秒输出一次for里面的 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("rose:啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"); 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) { e.printStackTrace(); } } } }; rose.start(); //设置守护线程必须在线程启动前进行 jack.setDaemon(true); jack.start(); } }
4.线程的相关属性
public class Thread_Info { public static void main(String[] args) { //取运行main方法的线程 Thread main = Thread.currentThread(); //获取线程ID long id = main.getId(); System.out.println("id:"+id); //获取线程名 String name = main.getName(); System.out.println("name:"+name); //是否处于活动状态 boolean isAlive = main.isAlive(); System.out.println("isAlive:"+isAlive); //是否为守护线程 boolean isDaemon = main.isDaemon(); System.out.println("isDaemon:"+isDaemon); //是否是被中断 boolean isInterrupted = main.isInterrupted(); System.out.println("isInterrupted:"+isInterrupted); } }
5.线程的阻塞,join方法
/** * 线程是异步运行的 * 异步:合执行各的,互相不妨碍 * 同步:有先后顺序的执行。 * * 有些业务需要让多个线程同时同步进行,这时候可以借助线程的join方法来完成 * * join方法允许一个线程进入阻塞状态,直到其等待的另一个线程工作结束后再继续运行。 */ public class Thread_join { public static boolean isFinish = false; public static void main(String[] args) { final Thread download = new Thread(){ public void run(){ System.out.println("dowm:开始下载图片..."); for(int i = 1;i<=100;i++){ System.out.println("down:"+i+"%"); try { Thread.sleep(10);//阻塞 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("down:图片下载完毕!"); isFinish = true; } }; Thread show = new Thread(){ public void run(){ System.out.println("show:开始显示图片..."); try { download.join(); } catch (InterruptedException e) { e.printStackTrace(); } /* * 先等待下载线程将图片下载完毕,再加载 */ if(!isFinish){ throw new RuntimeException("图片加载失败!"); } System.out.println("show:显示图片完毕!"); } }; download.start(); show.start(); } }
6.线程池的使用
/** * 线程池 * 线程池通常用于: * 1.控制线程数量 * 2.重用线程 * * @author tarena * */ public class ThreadPoolDemo { public static void main(String[] args) { ExecutorService threadPoo1 = Executors.newFixedThreadPool(2);//线程池中包含了2个线程 for(int i = 0;i<5;i++){//5个任务 Runnable runn = new Runnable(){ public void run(){ Thread t = Thread.currentThread(); System.out.println(t.getName()+":正在执行任务"); try { Thread.sleep(5000); } catch (InterruptedException e) { } System.out.println(t.getName()+":任务执行完毕"); } }; threadPoo1.execute(runn); System.out.println("将任务"+i+"指派给线程池"); } //停止线程池 threadPoo1.shutdownNow(); System.out.println("停止了线程池"); } }
线程小知识:
线程存在多线程并发安全问题,即当多个线程同时操作同一资源时,会出现“抢”的情况。由于多线程切换时机不定,可能导致代码执行顺序出现混乱,有悖于程序设计的执行顺序而出现逻辑错误,严重时可能导致系统瘫痪。
个人学习随笔,若是帮助到您,请给个推荐,或者评论一下下,谢谢了哟。若有不懂之处,请联系QQ:351094262(验证信息:博客园),原创不易,转载请标明出处!