线程中的一些方法

线程加入:public final void join()

  等待该线程终止,其他线程才能抢着执行。

练习代码如下:   

 1 public static void main(String[] args) {
 2         //创建三个线程
 3         MyThread mt1 = new MyThread();
 4         MyThread mt2 = new MyThread();
 5         MyThread mt3 = new MyThread();
 6
 7         //给线程起名字
 8         mt1.setName("刘备");
 9         mt2.setName("曹操");
10         mt3.setName("孙权");
11
12         //开启三个线程
13         mt1.start();
14
15         //接着让mt1这个线程设置为加入线程,其他线程就没有抢占cpu执行权的权利了,只能等待该线程执行完毕之后,才能开始抢占
16         try {
17             mt1.join();
18         } catch (InterruptedException e) {
19             // TODO Auto-generated catch block
20             e.printStackTrace();
21         }
22
23
24         mt2.start();
25         mt3.start();
26
27     }

线程加入练习

线程礼让:public final void yield()

  暂停当时正在执行的县城对象,并执行其他线程。

作用:让线程间的执行更和谐,但实际上做不到。

练习代码下:

 1 public class MyThread extends Thread{
 2     @Override
 3     public void run() {
 4         for (int i = 0; i < 100; i++) {
 5             System.out.println(getName()+"---"+i);
 6             //实现线程礼让
 7             Thread.yield();
 8         }
 9     }
10
11 }

线程礼让

线程死亡:

public final void stop():直接杀死。

练习代码如下:

run方法

 1 MyThread mt = new MyThread();
 2
 3         //开启线程对象
 4         mt.start();
 5
 6         //在线程处于睡眠的过程中将他杀死
 7
 8         try {
 9             Thread.sleep(3000);
10             //杀死刚刚开启的线程
11             //调用stop()方法将线程直接杀死
12             mt.stop();//划了一条横线表示该方法已经过时,但是还可以使用
13         } catch (InterruptedException e) {
14             // TODO Auto-generated catch block
15             e.printStackTrace();
16         }

stopTest

结果如下:

public void interrupt():直接杀死,在死前还有遗言。

练习代码:

 1 public void run() {
 2         //打印一下开始执行的时间
 3         System.out.println("开始时间:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
 4         //休眠10秒钟
 5         try {
 6             Thread.sleep(10000);
 7         } catch (InterruptedException e) {
 8             // TODO Auto-generated catch block
 9             //e.printStackTrace();
10             System.out.println("我被杀死了");
11         }
12         System.out.println("结束时间:"+new SimpleDateFormat("HH:mm:ss").format(new Date()));
13     }

run方法

 1 MyThread mt = new MyThread();
 2
 3         //开启线程对象
 4         mt.start();
 5
 6         //在线程处于睡眠的过程中将他杀死
 7
 8         try {
 9             Thread.sleep(3000);
10             //杀死刚刚开启的线程
11             //interrupt():直接杀死,在死前,还可以有遗言。
12             mt.interrupt();//线程被杀死之后会将后面的代码执行完毕之后,再死去
13
14         } catch (InterruptedException e) {
15             // TODO Auto-generated catch block
16             e.printStackTrace();
17         }

interruptTest

线程休眠:

static void sleep(lang millis):

在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。

线程间通信(生产消费者问题):不同类型线程针对同一个资源操作。我们常见一个Student对象,然后再创建一个设置Student对象的线程和一个获取Student对象的线程。

1 public class Student {
2     String name;
3     int age;
4 }

Student类

public class SetThread implements Runnable{private Student s;private int x=0;public SetThread(Student s){this.s = s;}@Overridepublic void run() {//给学生对象设置姓名和年龄//Student s = new Student();while (true) {synchronized (s) {if (x%2==0) {s.name = "大明";s.age = 14;}else {s.name = "陈小宝";s.age = 12;}x++;}}}}

SetStudent

 1 public class GetThread implements Runnable{
 2     private Student s;
 3
 4     public GetThread(Student s){
 5         this.s = s;
 6     }
 7     @Override
 8     public void run() {
 9         //获取线程,获取学生对象的姓名和年龄
10         //Student s = new Student();
11         while (true) {
12             synchronized (s) {
13                 System.out.println(s.name+"--"+s.age);
14             }
15         }
16     }
17
18 }

GetStudent

 1 public class StudentDemo {
 2     public static void main(String[] args) {
 3         //创建一个学生对象
 4         Student s = new Student();
 5
 6         //创建设置和获取线程,并开启线程
 7         SetThread st = new SetThread(s);
 8         GetThread gt = new GetThread(s);
 9
10         Thread t1 = new Thread(st);
11         Thread t2 = new Thread(gt);
12
13         //开启线程
14         t1.start();
15         t2.start();
16
17     }
18
19 }

StudentDemo

当我们运行这些代码时我们会发现一些问题,就是陈小宝和大明并不是交替出现的而是一个人出现好多次才出现另一个人。这是因为CPU的运行速的很快,而两个线程的抢占是随机的。

用wait方法和notify方法改进上述案例。

1 public class Student {
2     String name;
3     int age;
4     boolean flag;//在这里可以作为对象的一个标记,如果是false说明该对象没有数据,如果是true说明该对象有数据
5
6 }

改进后的Student类

 1 public class SetThread implements Runnable{
 2     private Student s;
 3     private int x = 0;
 4
 5     public SetThread(Student s){
 6         this.s = s;
 7     }
 8     @Override
 9     public void run() {
10         while (true) {
11             synchronized (s) {
12                 //判断该对象此时有没有数据
13                 if (s.flag) {
14                     //等待
15                     try {
16                         s.wait();//设置线程等待,释放锁s
17                     } catch (InterruptedException e) {
18                         // TODO Auto-generated catch block
19                         e.printStackTrace();
20                     }
21                 }
22
23                 if (x%2==0) {
24                     s.name = "大明";
25                     s.age = 14;
26                 }else {
27                     s.name = "陈小宝";
28                     s.age = 13;
29                 }
30                 x++;//x=1
31
32                 //此时对象有数据了
33                 s.flag = true;
34                 s.notify();//如果有等待的线程就唤醒,如果没有等待的线程,则没有任何效果
35             }//在此时释放锁对象s
36         }
37
38     }

改进后的SetStudent类

 1 public class GetThread implements Runnable{
 2     private Student s;
 3
 4     public GetThread(Student s){
 5         this.s = s;
 6     }
 7
 8     @Override
 9     public void run() {
10         while (true) {
11             synchronized (s) {
12                 //判断对象有没有数据
13                 if (!s.flag) {
14                     //等待设置线程给对象设置数据
15                     try {
16                         s.wait();//获取线程处于等待状态,释放锁对象s,在哪里跌倒在哪里爬起来
17                     } catch (InterruptedException e) {
18                         // TODO Auto-generated catch block
19                         e.printStackTrace();
20                     }
21                 }
22
23                 System.out.println(s.name+"--"+s.age);
24
25                 //当获取线程从学生对象中获取了数据之后,我们就默认他已经没有数据了,此时我们应该
26                 //继续让设置线程继续给学生对象设置信息
27                 s.flag = false;
28                 s.notify();
29             }
30         }
31
32     }
33
34 }

改进后的GetStudent类

当此程序运行时就不会出现一个人名连续出现好多次的情况了;

结果如下:

这个代码有一些绕,要细细的揣摩才能想明白。

线程池
为什么要使用线程池?
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,
尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。

线程池的特点:
线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池

线程池如何创建
JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newFixedThreadPool(int nThreads)

线程池的使用步骤:
1.创建线程池对象
ExecutorService pool = Executors.newFixedThreadPool(2);

2.创建Runnable实例
MyRunnable my = new MyRunnable();

3.提交Runnable实例
pool.submit(my);
pool.submit(my);

4.关闭线程池
pool.shutdown();

练习代码:

 1 public class MyCallable implements Callable{
 2     //也是一个任务,只不过这个任务需要执行的方法是call(),这个方法有返回值
 3     @Override
 4     public Object call() throws Exception {
 5         for (int i = 0; i < 100; i++) {
 6             System.out.println(Thread.currentThread().getName()+"---"+i);
 7         }
 8         return null;
 9     }
10
11 }

MyCallable

 1 public class ThreadPool {
 2     public static void main(String[] args) {
 3         //案例2:实现Callable接口实现线程池的使用
 4         //1.创建线程池
 5         ExecutorService pool = Executors.newFixedThreadPool(2);
 6
 7         //创建一个任务
 8         MyCallable my1 = new MyCallable();
 9         MyCallable my2 = new MyCallable();
10
11         //3.提交任务
12         pool.submit(my1);
13         pool.submit(my2);
14
15         //4.关闭线程池
16         pool.shutdown();
17
18     }

ThreadPool

 1 public class MyRunnbale implements Runnable {
 2
 3     @Override
 4     public void run() {
 5         for (int i = 0; i < 100; i++) {
 6             System.out.println(Thread.currentThread().getName()+"---"+i);
 7         }
 8
 9     }
10
11 }

MyRunnable

 1 public static void main(String[] args) {
 2         //线程池如何创建?
 3         //1.调用工厂类Executors
 4         //的public static ExecutorService newFixedThreadPool(int nThreads),返回一个线程池对象
 5         ExecutorService pool = Executors.newFixedThreadPool(2);
 6
 7         //2.提交给线程池两个任务,都是打印0-99
 8         //创建任务
 9         MyRunnbale my1 = new MyRunnbale();
10         MyRunnbale my2 = new MyRunnbale();
11
12         //3.提交任务
13         pool.submit(my1);
14         pool.submit(my2);
15
16         //关闭线程池
17         //void shutdown()
18         pool.shutdown();

View Code

定时器
Timer
public Timer()构造
public void schedule(TimerTask task, long delay)延迟多久执行任务
public void schedule(TimerTask task,long delay,long period)延迟多久执行任务,并以后每隔多久执行一次
public boolean cancel()取消这个任务

 1 public class TimerTest {
 2     public static void main(String[] args) {
 3         //需求:在10秒钟后,在控制台打印一句话,helloworld
 4         //public Timer()构造
 5         Timer t = new Timer();
 6
 7         //public void schedule(TimerTask task, long delay)延迟多久执行任务
 8         t.schedule(new MyTimerTask(t), 10000);
 9
10         //public void cancel()终止此计时器
11         //t.cancel();//如果在这里关闭的话,我们还没等任务执行完毕呢,计时器已经被关闭了
12
13     }
14
15 }
16
17 //创建TimerTask的子类
18 class MyTimerTask extends TimerTask{
19     private Timer t;
20     public MyTimerTask(Timer t){
21         this.t = t;
22     }
23
24     @Override
25     public void run() {
26         //此计时器任务要执行的操作。
27         System.out.println("helloworld");
28         t.cancel();//当任务被执行完毕之后,关闭定时器
29     }
30
31 }

TimerTask

转载于:https://www.cnblogs.com/shaofanglazi/p/6900928.html

Java学习:多线程(2)相关推荐

  1. Java学习--多线程

    1.实现多线程 1.1简单了解多线程[理解] 是指从软件或者硬件上实现多个线程并发执行的技术. 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能. 1.11多线程实现三种方式( ...

  2. java 学习~多线程通信 使用共享变量 例子和解释

    多线程互相通信一般使用共享变量.. 完整验证代码: main 方法 public class Test5 {public static void main(String[] args) {Datax ...

  3. Java学习笔记(7)——Java基础之IO多线程网络思维导图

    Java面向对象学习笔记之:包括IO(字节流,字符流,节点流,处理流).线程(线程创建,线程控制,线程同步).网络(TCP Scoket,  UDP Scoket)(全屏观看Java学习笔记(7)-- ...

  4. 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁

    什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...

  5. Java学习笔记5-1——多线程

    目录 前言 核心概念 线程创建 继承Thread类 实现Runnable接口 上述两个方法小结 实现Callable接口 并发问题简介 静态代理模式 线程状态 线程停止(stop) 线程休眠(slee ...

  6. Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍

    1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...

  7. java多线程阶乘_【java学习记录】11.用多线程实现阶乘的计算过程和结果的读取(thread类ReadThread )...

    (源码在上传的压缩包"[java学习记录]11.多线程实现阶乘计算(Thread类和Runnable接口)"中可看到,该压缩包可下载)java * 采用Thread类的子类实现线程 ...

  8. Java学习记录五(多线程、网络编程、Lambda表达式和接口组成更新)

    Java学习记录五(多线程.网络编程.Lambda表达式和接口组成更新) Java 25.多线程 25.1实现多线程 25.1.1进程 25.1.2线程 25.1.3多线程的实现 25.1.4设置和获 ...

  9. Java 学习 Day17 多线程

    Java 学习 Day17 文章目录 Java 学习 Day17 一.基本概念:程序.进程.线程 二.线程的创建和使用 三.多线程的创建,方式一:继承于Thread类 四. 创建多线程的方式二:实现R ...

  10. Java学习笔记2 多线程简单总结

    多线程简单总结 1. 相关概念 1.1 线程与进程 进程 线程 1.2 线程调度 分时调度 抢占式调度 1.3 同步与异步 同步 异步 1.4 并发与并行 并发 并行 2. 创建线程 2.1 继承Th ...

最新文章

  1. 从零开始写一个武侠冒险游戏-3-地图生成
  2. 关于谷歌浏览器 点击元素便签出现外边框的情况解决办法
  3. Spring Boot 线程池的创建、@Async 配置步骤及注意事项
  4. QT学习:字符串类QString
  5. .Net页面中使用在线编辑框实例
  6. 实现Fragment的切换和ViewPager自动循环设置切换时间
  7. Linux常用命令之yum
  8. [转]ie6下CSS存在的BUG
  9. 读取GY-951模块数据(Linux)
  10. Python工程师面试题目
  11. mybatisPlus代码自动生成
  12. labview混合编程学习
  13. Setup Factory打包winform程序
  14. 面向Java程序员的Scala教程
  15. Adobe Reader无法将数值DisableExceptionChainValidation写入键
  16. 描述性物理海洋学--第一章学习笔记
  17. 51Nod1584 加权约数和-题解
  18. DL645通信协议97/07规约
  19. 指令集创始人潘爱民受邀出席CCF系统软件技术论坛,探讨泛在操作系统技术发展...
  20. 2013年CISA考试知识点变化总结讲义

热门文章

  1. 对cocos2dx引擎的改动
  2. Fragment:support.v4.content.Loader.deliverResult
  3. download first at netease music
  4. what to do preparing for phd
  5. deepl真的有取代一般翻译的能力,这吞吐量和稳定性...亲测有效
  6. 接着做!一往无前!冲!就是我的信条!
  7. 反射调用private或internal构造函数
  8. 我们常常意识不到问题的存在,直到有人解决了这些问题
  9. Linux下Web网站压力测试工具Webbench
  10. mapper中的CDATA标签的用法