Java多线程总结(一)
2015-06-30 16:38
435 查看
1.多线程的优势:同时运行多部分代码;劣势:效率降低。JVM在启动的时候,至少启动了两个线程,执行main函数的线程,垃圾回收线程。
2.垃圾回收机制,System.gc()方法告诉JVM调用finalize方法,但不一定立即执行。
3.创建线程的方式:第一种:继承Thread类。示例如下:
.
4.第二种:实现Runnable接口:优点:将线程的任务从线程的子类中分离出来,进行了单独的封装,按照面向对象的思想将任务封装成对象。示例如下:
.
5.Thread类,Runnable接口模拟实现,如下:
.
6.线程安全问题示例:
.
7.线程安全问题产生的原因:1.多个线程在操作共享的数据;2.操作共享数据的线程代码有多条。由此可知,当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。
8.解决线程安全问题的方案:将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程不能参与运算。必须要当前线程把这些代码都执行完毕,其他线程才能参与运算。
9.同步代码块:修饰词:synchronized.同步的好处:解决了线程的安全问题;弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中降低程序运行的效率。同步的前提:必须有多个线程使用同一个锁。
10.Synchroized修饰的函数锁是this,修饰的静态变量,锁是类的字节码文件,修饰的成员变量,锁可以是任意对象。
11.同步示例:
.
12.多线程下的单例设计模式:1.饿汉式:不存在多个线程共同操作数据的情况,线程安全。
2.懒汉式:存在线程安全问题。
.
13.死锁:想要获取的锁被别的线程所占有,互相不释放,导致程序不能继续执行下去。死锁示例:
.
14.多线程间的通信:多个线程在处理统一资源,但是任务不同,这时就需要多线程间的通信。等待/唤醒机制涉及的方法:1.wait(),让线程处于冻结状态,被wait()的线程会放在线程池中;2.notify(),唤醒线程池中的一个线程;3.notifyAll(),唤醒线程池中的所有线程。PS:wait释放执行权,释放锁。以上三个方法都定义在同步中,因为这些方法是用于操作线程状态的方法。
15.一对一的线程通信,线程被唤醒之后,会继续从之前wait的部分之后开始执行任务。一对一线程通信如下:
2.垃圾回收机制,System.gc()方法告诉JVM调用finalize方法,但不一定立即执行。
3.创建线程的方式:第一种:继承Thread类。示例如下:
package heima.person.caizhanqi.basetest; public class ThreadDemo extends Thread { @Override public void run() { // TODO Auto-generated method stub super.run(); for (int i = 0; i < 10; i++) { System.out.println( Thread.currentThread().getName() +"-----------"+this.getId()); } } public static void main(String[] args) { new ThreadDemo().start(); for (int i = 0; i < 10; i++) { +"-----------" +Thread.currentThread().getId()); } new ThreadDemo().start(); new ThreadDemo().start(); } }
.
4.第二种:实现Runnable接口:优点:将线程的任务从线程的子类中分离出来,进行了单独的封装,按照面向对象的思想将任务封装成对象。示例如下:
public class ThreadDemo implements Runnable { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName() + "--------"+ i + "--------" + Thread.currentThread().getId()); } } public static void main(String[] args) { ThreadDemo demo = new ThreadDemo(); new Thread(demo).start(); new Thread(demo).start(); new Thread(demo).start(); } }
.
5.Thread类,Runnable接口模拟实现,如下:
public class ThreadDemo{ private Runnable r; public ThreadDemo(){ } public ThreadDemo(Runnable r){ this.r = r; } public void run(){ if(r!=null) r.run(); } public void start(){ run(); } }
.
6.线程安全问题示例:
public class ThreadSecurity implements Runnable { private int num; public ThreadSecurity() { // TODO Auto-generated constructor stub } public ThreadSecurity(int num) { this.num = num; } @Override public void run() { while (num > 0) { try { System.out.println( Thread.currentThread().getName() + "----sale..."+ num); num--; Thread.sleep(100); } catch (Exception e) { // TODO: handle exception } } } public static void main(String[] args) { ThreadSecurity t = new ThreadSecurity(10); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } }
.
7.线程安全问题产生的原因:1.多个线程在操作共享的数据;2.操作共享数据的线程代码有多条。由此可知,当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。
8.解决线程安全问题的方案:将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程不能参与运算。必须要当前线程把这些代码都执行完毕,其他线程才能参与运算。
9.同步代码块:修饰词:synchronized.同步的好处:解决了线程的安全问题;弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中降低程序运行的效率。同步的前提:必须有多个线程使用同一个锁。
10.Synchroized修饰的函数锁是this,修饰的静态变量,锁是类的字节码文件,修饰的成员变量,锁可以是任意对象。
11.同步示例:
public class ThreadSynchronized implements Runnable { private int num; private boolean flag; public ThreadSynchronized() { flag = true; num = 100; } @Override public void run() { if (flag) { while (true) { synchronized (this) { if (num > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println( Thread.currentThread().getName() + "--true--" + num--); } } } } else { while (true) show(); } } public synchronized void show() { if (num > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println( Thread.currentThread().getName() + "--flase--" + num--); } } public static void main(String[] args) { ThreadSynchronized ts = new ThreadSynchronized(); new Thread(ts).start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } ts.flag = false; new Thread(ts).start(); new Thread(ts).start(); } }
.
12.多线程下的单例设计模式:1.饿汉式:不存在多个线程共同操作数据的情况,线程安全。
class SingleThread{ private static final SingleThread s = new SingleThread(); private SingleThread(){} public SingleThread getSingleThread(){ return s; } }
2.懒汉式:存在线程安全问题。
Class SingleThread{ private static final SingleThread s = null; Private SingleThread(){} public SingleThread getSingleThread(){ if(s == null){ sysnchronized(SingleThread.class){ if(s == null){ S = new SingleThread(); } } } return s; } }
.
13.死锁:想要获取的锁被别的线程所占有,互相不释放,导致程序不能继续执行下去。死锁示例:
public class DeadLock implements Runnable { private int num = 1000; private boolean flag; private Object obj = new Object(); @Override public void run() { if (flag) { while (true) { synchronized (obj) { if (num > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println( Thread.currentThread().getName() + "--true--" + num--); } show(); } } } else { while (true) { show(); } } } public synchronized void show() { synchronized (obj) { if (num > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "--false--" + num--); } } } public static void main(String[] args) { DeadLock dl = new DeadLock(); dl.flag = true; new Thread(dl).start(); new Thread(dl).start(); try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } dl.flag = false; new Thread(dl).start(); } }
.
14.多线程间的通信:多个线程在处理统一资源,但是任务不同,这时就需要多线程间的通信。等待/唤醒机制涉及的方法:1.wait(),让线程处于冻结状态,被wait()的线程会放在线程池中;2.notify(),唤醒线程池中的一个线程;3.notifyAll(),唤醒线程池中的所有线程。PS:wait释放执行权,释放锁。以上三个方法都定义在同步中,因为这些方法是用于操作线程状态的方法。
15.一对一的线程通信,线程被唤醒之后,会继续从之前wait的部分之后开始执行任务。一对一线程通信如下:
class Resource{ private int num = 0; private boolean flag; public void setResource(){ synchronized(this){ System.out.println("set...wait"); if(flag) try { Thread.sleep(100); wait(); } catch (Exception e) { e.printStackTrace(); } System.out.println("set....notify"); num++; flag = true; System.out.println("in...."+num); notify(); } } public void outResource(){ synchronized(this){ System.out.println("out...wait"); if (!flag) try { Thread.sleep(100); wait(); } catch (Exception e) { e.printStackTrace(); } System.out.println("out...notify"); System.out.println("out...."+num); flag = false; notify(); } } } class InDemo implements Runnable{ private Resource r; public InDemo(Resource r) { this.r = r; } @Override public void run() { while(true){ r.setResource(); } } } class OutDemo implements Runnable{ private Resource r; public OutDemo(Resource r) { this.r = r; } @Override public void run() { while(true) r.outResource(); } } public class ThreadDemo{ public static void main(String[] args) { Resource r = new Resource(); InDemo in = new InDemo(r); OutDemo out = new OutDemo(r); new Thread(in).start(); new Thread(out).start(); } }
相关文章推荐
- eclipse中英文大小不一致解决方法
- struts2 Double类型上传默认转换为String
- spring Could not resolve placeholder
- 连接mysql报Communication link failure: java.io.IOException, underlying cause: Unexpected end of input s
- Java常用工具包 Jodd
- JavaWeb学习记录(八)——servlet获取配置信息
- JavaWeb学习记录(七)——MVC操作数据库增删改查与分页功能
- TestNg JAVA 自动化单元测试框架Demo
- TestNg JAVA 自动化单元测试框架Demo
- 2、javaweb listener 对象的属性变更--监听
- 【Spring学习笔记-MVC-16】Spring MVC之重定向-解决中文乱码
- 浅谈Eclipse的内存分析工具MAT(一)
- 管中窥探java虚拟机(一)
- Eclipse 打不开
- java内存泄漏的定位与分析
- Java多线程编程总结
- MyEclipse创建自己类库
- 【Java Swing探索之路系列】之二:Java Swing布局面板组件
- SpringMVC 的 Controller 返回各种视图的处理方式
- JavaWeb学习记录(三)——网页中文编码问题