java中的多线程问题
来源:互联网 发布:澳大利亚土木工程知乎 编辑:程序博客网 时间:2024/05/17 07:09
1.什么是进程,线程,多线程
进程是系统中正在运行的程序
线程是进程的执行单元,执行路径
多线程是多个线程并发执行的技术.
2.什么情况下使用多线程:
(1).单线程不能满足业务需要.比如火车票售票系统,在同一时间可能有多个请求,这些请求之间是相互独立的,没有依赖关系,后台必须通过多线程保证对用户的及时响应.
(2).单线程不能满足性能要求,通过多线程提高效率.比如,多线程可以用一个线程专门用于读写文件,其他的线程用于对读取数据进行处理,这样才有可能更好地利用 CPU 资源。
3.什么是线程安全
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码,如果每次运行结果和单线程运行的结果是一样的,那就是线程安全的。如果运行结果和单线程的运行结果不同,就为线程不安全.
4.多线程的两种实现方式
(1)继承Thread,重写run()方法
public class MyThread extends Thread { @Override public void run() { for (int x = 0; x < 100; x++) { System.out.println(getName()+ x); } }}
(2)实现Runnable,重写run()方法
public class MyRunnable implements Runnable { @Override public void run() { for (int x = 0; x < 100; x++) { // getName()方法是Thread类的,而MyRunnable只实现了 Runnable接口,本身没有getName(),所以不能使用。 System.out.println(Thread.currentThread().getName() + "---hello"+ x); } }}一般使用第二种方式,因为方式一只能单继承,有一定的局限性,而方式二只创建一个对象,实现了数据和操作更好的分离.
5.通过火车票案例了解多线程(四个窗口同时出售火车票)
public class TicketRunnable implements Runnable {private static int tickets = 100;@Overridepublic void run() { while (true) { //通过加锁,保证线程安全 synchronized (this) { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } else { break; } } }}}
主函数
public class RunnableTest {public static void main(String[] args) { TicketRunnable tr = new TicketRunnable(); Thread t1 = new Thread(tr,"窗口1"); Thread t2 = new Thread(tr,"窗口2"); Thread t3 = new Thread(tr,"窗口3"); Thread t4 = new Thread(tr,"窗口4"); t1.start(); t2.start(); t3.start(); t4.start();}}注:(1).多线程中的锁对象可以为任意对象,但必须为同一对象 静态方法锁对象:是当前类的字节码文件对象 类名.class (2).解决线程同步问题的两种方式 a、同步代码块 synchronized(锁对象) {....} //锁对象可以是任意类型 b、同步方法 格式:public synchronized 返回值 方法名(){....} 锁对象:this(3)如何判断线程是否安全 a、看有没有共享数据 b、看操作共享数据的语句是不是多条语句 c、看是不是在多线程的环境中
6.线程死锁问题
public class DieLock extends Thread {private boolean flag;public DieLock(boolean flag) { this.flag = flag;}@Overridepublic void run() { if (flag) { synchronized (MyLock.objA) { System.out.println("true -- objA"); synchronized (MyLock.objB) { System.out.println("true -- objB"); } } } else { synchronized (MyLock.objB) { System.out.println("false -- objB"); synchronized (MyLock.objA) { System.out.println("false -- objA"); } } }}}死锁原因总结 线程1自身拿着一个锁:A锁,线程2自身拿着一个锁:B锁 当线程1要用B锁,线程B要用A锁的时候就会发生死锁如何避免死锁: 不嵌套使用锁
7.线程的优先级
1、线程优先级级别 线程默认优先级是5。范围是1-10 Thread.MAX_PRIORITY //10 Thread.MIN_PRIORITY //1 Thread.NORM_PRIORITY //52、方法 public final int getPriority():获取线程优先级 public final void setPriority(int newPriority):更改线程的优先级3、注意 优先级可以在一定的程度上,让线程获较多的执行机会4、举例 MyThread t = new MyThread(); System.out.println(t.getPriority()); t.setPriority(Thread.MAX_PRIORITY);
8.线程的等待唤醒机制
(1).前提: 两个线程共用一把锁,此时可以调用该锁的wait和notify方法,实现等待唤醒机制
(2)sleep和wait的区别
wait:是Object类的方法,可以不用传递参数,释放锁对象
sleep:是Thread类的静态方法,需要传递参数
案例:多线程实现设置和获取学生信息
Student类
public class Student {private String name;private int age;private boolean flag = false;public synchronized void set(String name, int age) { // 如果有数据就等待 if (this.flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 设置值 this.name = name; this.age = age; // 修改标记 this.flag = true; this.notify();}public synchronized void get() { // 如果没有数据就等待 if (!this.flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 获取值 System.out.println(this.name + "***" + this.age); // 修改标记 this.flag = false; this.notify();}}
SetStudent类
public class SetStudent implements Runnable {private Student s;public SetStudent(Student s) { this.s = s;}@Overridepublic void run() { int x = 0; while (true) { if (x % 2 == 0) { s.set("林青霞", 26); } else { s.set("刘意", 29); } x++; }}}
GetStudent类
public class GetStudent implements Runnable {private Student s;public GetStudent(Student s) { this.s = s;}@Overridepublic void run() { while (true) { s.get(); }}}
StudentTest测试类
public class StudentTest {public static void main(String[] args) { Student s = new Student();// 资源类 SetStudent ss = new SetStudent(s); GetStudent gs = new GetStudent(s); Thread t1 = new Thread(ss); Thread t2 = new Thread(gs); t1.start(); t2.start();}}
0 0
- Java中的多线程问题
- Java中的多线程问题
- java中的多线程问题
- Java多线程中的两个问题
- Java多线程中的两个问题
- Java程序中的多线程问题
- java面试中的多线程问题
- Java面试中的多线程问题
- JAVA面试中的多线程问题
- Java面试中的多线程问题
- [Java]Java程序员面试中的多线程问题
- Java程序员面试中的多线程问题
- Java程序员面试中的多线程问题
- Java程序员面试中的多线程问题
- Java程序员面试中的多线程问题
- Java程序员面试中的多线程问题
- Java程序员面试中的多线程问题
- Java程序员面试中的多线程问题
- 【笔试】37、顺时针打印矩阵
- 上传SVN中,如何屏蔽掉gen文件和bin文件
- Sparse Autoencoder Exercise
- 【spring框架】(一)spring简介
- 二叉搜索树的后序遍历序列
- java中的多线程问题
- 解决firefox弱临时 Diffie-Hellman 密钥的错误
- Hadoop常见错误及解决办法汇总
- 构造url测试action与dao实例
- 服务器硬件/系统信息查询
- 面试题16:翻转链表
- HDU 3743 Frosh Week(逆序对-BIT)
- liunx-fastboot命令行的使用方法
- java中将file文件对象转string