Java线程--扩展
Java线程--扩展
扩展一些Java线程的知识。
首先说一下线程相关的常用类:
1. Timer:定时器、调度器、计时器。
2. TimerTask:定时任务。
下面根据这两个类写一个欢迎界面:
import java.awt.BorderLayout; importjava.awt.CardLayout; import java.util.Timer; import java.util.TimerTask; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import com.sun.awt.AWTUtilities; publicclassLogoextends JFrame{ privateintniIndex = 1; private JLabel jbShow; private Timer timer; public Logo(){ JPanel pnBasic = new JPanel(); //设置布局为东西南北中布局 pnBasic.setLayout(new BorderLayout()); jbShow = new JLabel(); //添加图片,图片的路径可以自己设定 jbShow.setIcon(new ImageIcon("p_w_picpath\\logo\\1.png")); //把标签添加进来吗,并放在中间的位置 pnBasic.add(jbShow,BorderLayout.CENTER); setContentPane(pnBasic); //下面两句是设置窗口透明 setUndecorated(true); AWTUtilities.setWindowOpaque(this, false); //设置标题 setTitle("欢迎界面"); //设置窗口大小 setBounds(200,200,500,400); //设置窗口自适应 pack(); //设置推出方式 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置窗口可见 setVisible(true); //创建定时器 timer = new Timer(); //安排指定的任务在指定的时间开始进行重复的固定延迟执行 //task - 所要安排的任务 //firstTime - 首次执行任务的时间 //period - 执行各后续任务之间的时间间隔,单位是毫秒 timer.schedule(new LogoMoniter(),1000,500); } privateclass LogoMoniter extends TimerTask{ @Override publicvoid run() { if(niIndex<7){ niIndex++; jbShow.setIcon(new ImageIcon("p_w_picpath\\logo\\"+niIndex+".png")); }else{ //终止此计时器,丢弃所有当前已安排的任务 timer.cancel(); //销毁窗口 dispose(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //两秒之后再控制台输出hello System.out.println("hello"); } } } publicstaticvoid main(String[] args) { new Logo(); } } |
这是利用定时器做的一个简单的欢迎界面。我们可以自己添加图片,注意把图片的名字命名成数字.的形式,因为我们是根据for循环来获取图片名字的。 |
接下来说一个Java线程中的问题,比如我们去银行存取钱,如果网络存在一点延迟,假设你的亲人就在网络延迟的时候也在存取钱,那么可能最后的余额就会出现问题,下面通过程序来具体看一下:
publicclass Bank1 { publicstaticvoid main(String[] args) { Account1 account = new Account1(); Person you1 = new Person(account); Person youGF1 = new Person(account); Thread th1 = new Thread(you1); Thread th2 = new Thread(youGF1); th1.start(); th2.start(); try { Thread.sleep(4000);// 确保账户操作完毕 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("最终余额:" + account.balance); } } class Account1 { publicintbalance = 2000; //取钱 publicvoid withdraw() { int temp = balance; temp = temp - 800; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } balance = temp; System.out.println(Thread.currentThread().getName() + ":余额:" + this.balance); } } class Person implements Runnable { private Account1 account; public Person(Account1 account) { super(); this.account = account; } @Override publicvoid run() { account.withdraw(); } } |
这个程序完成的功能是两个人取同一个账户里的钱。 执行结果: Thread-0:余额:1200 Thread-1:余额:1200 最终余额:1200 |
通过结果可以看到,没取之前余额是2000,而两个人每次取的钱都是800,正常情况余额应该是400,这就是我们所说的问题,那么应该如何解决呢?
线程间的同步:本质:把异步转化为同步,把并行转为串行。
有两种方式可以解决:
1. 同步语句块:synchronized(obj){}
2. 同步方法:在方法前加synchronized修饰符,拿到的仍然是本类对象的锁。
难点:不容易测出来。
对象锁:每个对象都有一把锁。同步锁、互斥锁。
下面通过程序看一下:
publicclass Bank1 { publicstaticvoid main(String[] args) { Account1 account = new Account1(); Person you1 = new Person(account); Person youGF1 = new Person(account); Thread th1 = new Thread(you1); Thread th2 = new Thread(youGF1); th1.start(); th2.start(); try { Thread.sleep(4000);// 确保账户操作完毕 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("最终余额:" + account.balance); } } class Account1 { publicintbalance = 2000; private Object obj = new Object(); // 加了一把互斥锁,只能有一个线程执行 public/*synchronized*/void withdraw() { //两种方法 synchronized (obj) { int temp = balance; temp = temp - 800; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } balance = temp; System.out.println(Thread.currentThread().getName() + ":余额:" + this.balance); } } } class Person implements Runnable { private Account1 account; public Person(Account1 account) { super(); this.account = account; } @Override publicvoid run() { account.withdraw(); } } |
执行结果: Thread-0:余额:1200 Thread-1:余额:400 最终余额:400 |
通过上面的两种方式,我们可以看到余额正常了。
转载于:https://blog.51cto.com/libaiqiang/1268748
Java线程--扩展相关推荐
- 面试必问---Java线程池8大拒绝策略
前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的这个api,大大的简化了多线程代码的开发.而不论你用Fix ...
- Java线程怎样映射到操作系统线程
先说多线程模型,参考经典教材<Operating System Concepts , Silberschatz ,9th edition> 中文版是<操作系统概念,第9版> h ...
- 2017年50道Java线程面试题
下面是Java线程相关的热门面试题,你可以用它来好好准备面试. 1) 什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.程序员可以通过它进行多处理器编 ...
- Java线程面试题 Top 50(转)
不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎.大多数待遇丰厚的Java开发职位都要求开发者精通多线程 ...
- java线程池拒绝策略_Java核心知识 多线程并发 线程池原理(二十三)
线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后 启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕, 再从队列中取出任务来执行.他 ...
- Java 线程池必知的8 大拒绝策略
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | kailing.pub/article/ind ...
- 【多线程】Java线程面试题 Top 50(转载)
Java线程面试题 Top 50 原文链接:http://www.importnew.com/12773.html 本文由 ImportNew - 李 广 翻译自 javarevisited.欢迎加入 ...
- JAVA线程池管理及分布式HADOOP调度框架搭建
平时的开发中线程是个少不了的东西,比如tomcat里的servlet就是线程,没有线程我们如何提供多用户访问呢?不过很多刚开始接触线程的开发攻城师却在这个上面吃了不少苦头.怎么做一套简便的线程开发模式 ...
- Java 线程池框架核心代码分析--转
原文地址:http://www.codeceo.com/article/java-thread-pool-kernal.html 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和 ...
最新文章
- 局域网与网络工程课堂笔记(1)(2)
- java slf4j日志框架_SLF4J - 日志框架 - 类库 - Java - 代码树
- Mybatis字段模糊查询
- std::priority_queue
- 信息技术上册教案了解计算机,信息技术上册全册教案
- sql:命名管道管道程序_学习SQL:命名约定
- 微软电脑管家登陆微软商店 简单无打扰 支持杀毒和垃圾清理等
- 【1】使用分类学习APP - Classification Learner App 训练分类模型
- 从核酸检测平台崩盘看性能工程的范围
- 【Django | 开发】面试招聘网站(增加csv,excel导出企业域账号集成日志管理功能)
- 面试题:460道Java后端面试高频题答案版「模块九:Spring」
- java通过struts实现web中的文件上传
- http请求包与请求返回的是什么
- Linux运维学习路径全解析
- 实际参数与形式参数的区别
- AWS KVS(Kinesis Video Streams)之WebRTC移植编译(四)
- Python 修改AD账号密码(一)- 启用域控LDAPS
- 硕士卖房,到底是行业内卷,还是自我突破
- MB10F-ASEMI整流桥MB10F
- bq24773功能分析(中文手册翻译)
热门文章
- asp空间和php空间_免费ASP空间与免费PHP空间
- android电视怎么升级失败,智能电视升级失败,原因都在这里!
- 【BZOJ3238】差异,后缀数组+单调栈维护height
- 应用程序_构建应用程序12 条参考准则
- dh算法 理论依据_DH算法原理
- java web汽车商城_基于jsp的汽车销售商城系统
- vlan跨交换机 udp广播_网络交换VLAN基础入门
- 2017.9.26 于神之怒加强版 失败总结
- 【Level 08】U07 Mixed Feelings L4 Learning by heart
- 【英语学习】【Daily English】U14 Transportation L04 I'm going to go screen