JAVAThread 多线程学习
来源:互联网 发布:发现者行车记录仪淘宝 编辑:程序博客网 时间:2024/06/06 22:45
开始第二遍学习java了,发现有好多的知识点在之前学习的时候是不了解的。在java多线程的板块中,学到了除了继承Thread 实现runnable接口以外 还学到了第三种的基于线程池的实现callable接口的线程方式。感觉java真实博大精深。对java线程的笔记总结:
java线程
java程序由一条线程执行完毕 称为单线程程序
java程序由多条程序执行完毕 称为多线程程序
1:多线程
(1)多线程:一个应用程序有多条执行路径 进程:正在执行的应用程序 线程:进程的执行单元,执行路径 单线程:一个应用程序只有一条执行路径 多线程:一个应用程序有多条执行路径
多进程的意义? 提高CPU的使用率 多线程的意义? 提高应用程序的使用率(2)Java程序的运行原理及JVM的启动是多线程的吗? A:Java命令去启动JVM,JVM会启动一个进程,该进程会启动一个主线程。 B:JVM的启动是多线程的,因为它最低有两个线程启动了,主线程和垃圾回收线程。
(3)多线程的实现方案
A:继承Thread类
B:实现Runnable接口
* 两种方式的比较
(4)线程的调度和优先级问题
A:线程的调度
- a:分时调度
- b:抢占式调度 (Java采用的是该调度方式)
B:获取和设置线程优先级 a:默认是5 b:范围是1-10
(5)线程的控制(常见方法)
A:休眠线程
API方法:
线程睡眠毫秒数
- public static void sleep(long millis)
B:加入线程
API方法
join:等待线程终止,等待线程执行完毕后其它的线程才可以运行
- public final void join();
C:礼让线程
API方法
一定程度上让多个线程的执行和谐,不靠谱
- public static void yield()
D:后台线程
API方法
- public final void setDaemon(boolean on)
当正在运行的线程都是守护线程时,java虚拟机退出,该方法必须在线程启动之前调用
标记为守护线程后,线程会依附于某个线程,不会独立的run
E:终止线程(掌握)
API方法
public final void stop() 让线程停止,已过时
public void interrupt() 终止线程,并且抛出InterruptedException异常,并会执行后续的代码
线程的生命周期(参照 线程生命周期图解.bmp)
A:新建
创建线程对象的过程
B:就绪
有执行的条件和资格,没有执行权
c:运行
有运行的资格,有执行权
D:阻塞
没有执行资格,没有执行权
E:死亡
线程对象变成垃圾,等待被回收
(7)电影院卖票程序的实现 A:继承Thread类 B:实现Runnable接口(8)电影院卖票程序出问题 A:为了更符合真实的场景,加入了休眠100毫秒。 B:卖票问题 a:同票多次 b:负数票(9)多线程安全问题的原因(也是我们以后判断一个程序是否有线程安全问题的依据) A:是否有多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据
(10)同步解决线程安全问题
A:同步代码块
synchronized(对象) {
需要被同步的代码;
}
这里的锁对象可以是任意对象。
B:同步方法
把同步加在方法上。
这里的锁对象是this
C:静态同步方法
把同步加在方法上。
这里的锁对象是当前类的字节码文件对象(反射再讲字节码文件对象)
(11)回顾以前的线程安全的类
- A:StringBuffer
- B:Vector
- C:Hashtable
- D:如何把一个线程不安全的集合类变成一个线程安全的集合类用Collections工具类的方法即可。
相关知识点
(1)JDK5以后的针对线程的锁定操作和释放操作
Lock锁
// 定义锁对象 private Lock lock = new ReentrantLock(); @Override public void run() { while (true) { try { // 加锁 lock.lock(); if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } finally { // 释放锁 lock.unlock(); } } }
(2)死锁问题的描述和代码体现
- 是指两个或者两个以上的线程在执行的过程中,因争夺资源产一种互相等待现象
- 同步代码块的嵌套案例
@Overridepublic void run() { // 死锁代码 if (flag) { // 同步嵌套 synchronized (MyLock.objA) { System.out.println("if obja"); synchronized (MyLock.objB) { System.out.println("if objb"); } } } else { synchronized (MyLock.objB) { System.out.println("else objb"); synchronized (MyLock.objA) { System.out.println("else obja"); } } }}
(3)生产者和消费者多线程体现(线程间通信问题)
以学生作为资源来实现的 资源类:Student 设置数据类:SetThread(生产者) 获取数据类:GetThread(消费者) 测试类:StudentDemo 代码: A:最基本的版本,只有一个数据。 B:改进版本,给出了不同的数据,并加入了同步机制 C:等待唤醒机制改进该程序,让数据能够实现依次的出现 wait() 线程等待后立即释放所持有的锁,被唤醒后在等待的位置继续执行 notify() 唤醒并不代表立马可以执行 线程会转为就绪状态 等待下一次执行 notifyAll() (多生产多消费)
- 为什么定义在Object中?
- 这些方法的调用通过锁对象调用,而我们使用的锁可能是任意锁对象。所以,这些方法必须定义在Object类中 =* 等待唤醒机制的代码优化。把数据及操作都写在了资源类中
(4)线程组
- Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。 默认情况下,所有的线程都属于主线程组(main组)。
返回该线程所属的线程组 - public final ThreadGroup getThreadGroup()
我们也可以给线程设置分组 Thread(ThreadGroup group, Runnable target, String name)
新建线程组代码:// ThreadGroup(String name) ThreadGroup tg = new ThreadGroup("这是一个新的组"); MyRunnable my = new MyRunnable(); // Thread(ThreadGroup group, Runnable target, String name) Thread t1 = new Thread(tg, my, "林青霞"); Thread t2 = new Thread(tg, my, "刘意"); System.out.println(t1.getThreadGroup().getName()); System.out.println(t2.getThreadGroup().getName()); //通过组名称设置后台线程,表示该组的线程都是后台线程 tg.setDaemon(true);
(5)线程池
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池。
- 线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
- 在JDK5之前,我们必须手动实现自己的线程池,从JDK5开始,Java内置支持线程池
- JDK5新增了一个Executors工厂类来产生线程池,有如下几个方法
public static ExecutorService newCachedThreadPool()
创建一个具有缓存功能的线程池缓存:百度浏览过的信息再次访问
public static ExecutorService newFixedThreadPool(int nThreads)
创建一个可重用的,具有固定线程数的线程池
public static ExecutorService newSingleThreadExecutor()
创建一个只有单线程的线程池,相当于上个方法的参数是1
protected void shutdown()
顺序关闭线程池中的线程 这些方法的返回值是ExecutorService对象,该对象表示一个线程池,可以执行Runnable对象或者Callable对象代表的线程。它提供了如下方法
Future<?> submit(Runnable task)
Future submit(Callable task)
(6)多线程实现的第三种方案
实现Callable接口 步骤和刚才演示线程池执行Runnable对象的差不多。 但是还可以更好玩一些,求和案例演示 好处: 可以有返回值 可以抛出异常 弊端: 代码比较复杂,所以一般不用
匿名内部类方式使用多线程
new Thread(){代码…}.start(); New Thread(new Runnable(){代码…}).start();
多线程的应用
定时器的使用
描述:
定时器是一个应用十分广泛的线程工具,可用于调度多个定时任务以后台线程的方式执行。在Java中,可以通过Timer和TimerTask类来实现定义调度的功能
Timer 一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
public Timer()
public void schedule(TimerTask task, long delay)
public void schedule(TimerTask task,long delay,long period)
* TimerTask 任务类用于为Timer指定任务 public abstract void run()
public boolean cancel()
* 开发中
Quartz是一个完全由java编写的开源调度框架。线程的生命周期转换图:
- JAVAThread 多线程学习
- javaThread技术--学习笔记
- Andoird多线程基础:JavaThread & Handler & AsyncTask
- javaThread学习(chapter1—线程的创建)
- javaThread学习(chapter2—线程的并发访问)
- javaThread源码
- 三个实例演示JavaThread Dump 日志分析
- 学习多线程
- 多线程学习
- 多线程学习
- 多线程学习
- 多线程学习
- 多线程学习
- 多线程学习
- 学习多线程
- 多线程学习
- 多线程学习
- 多线程学习
- 编写自己的代码生成工具二:解析配置文件
- Windows下编译fast rcnn
- 从数组中找出一对元素,其和是一个给定的目标数字。假设数组中只存在一个符合要求的数值对,返回这些数值的下标
- 编写自己的代码生成工具三:代码生成组织者
- xUtils介绍
- JAVAThread 多线程学习
- 当你的网站被疯狂攻击时你能做什么?
- 编写自己的代码生成工具四:数据库信息查询实现
- SHELL笔记之让文本飞(四)
- CentOS 7 下 modutils-2.4.27 编译时遇到的问题
- com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1157 > 1024).
- eclipse配置maven + 创建maven项目(一)
- LoganSquare的简单使用——快到爆炸地解析和序列化JSON
- html运用(二) html5前端开发基础–html5 meta全解