多线程
来源:互联网 发布:男朋友是java工程师 编辑:程序博客网 时间:2024/05/29 08:55
首先我们来了解一下概念
进程:是一个正在执行的程序,每一个进程执行都有一个顺序,该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行。
一个进程中至少有一个线程。
Java VM 启动的时候会有一个进程java.exe
该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,该线程称之为主线程。
另:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。
多线程存在的意义:使用线程可以把占据时间长的程序中的任务放到后台去处理;用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度;程序的运行速度可能加快;在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了,在这种情况下可以释放一些珍贵的资源如内存占用等等。
线程的创建方式:
通过对API的查找,java已经提供了对线程这类事务的描述,就是Thread类,
创建线程的第一种方式,继承Thread类
步骤:
1.定义类继承Thread类
2.复写Thread类中的run方法,目的:把自定义要运行多线程的代码写入run方法中
3.调用线程的start方法,该方法的作用:启动线程,调用run方法
为什么要复写run方法?
Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法,也就是说,Thread类中的run方法,用于存储线程要运行的代码
发现每次运行结果都不同,因为多个线程都获取cpu的执行权,cpu执行到谁,谁就运行。
明确一点,在某一时刻,只能有一个程序在运行,多核除外。
cpu在做着快速切换,以达到看上去同时运行的效果。
我们可以形象的把多线程的运行行为看成是互相抢夺cpu的执行权
package first;public class ThreadTest { public static void main(String[] args) { ThreadDemo thread=new ThreadDemo();//创建好一个线程 thread.start(); //thread.run()//这样也可以运行,但没有多线程的效果,是先后运行的了 for(int i=0;i<10;i++){ System.out.println("main Run---->"+i); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } }}class ThreadDemo extends Thread{ public void run() {//复写run方法 for(int i=0;i<10;i++){ System.out.println("Thread Run*****"+i); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }}
线程的五种状态图:
冻结状态:又分为睡眠和等待两种状态。
临时状态:调用了start方法后,还在等待cpu来处理启动
冻结状态和临时状态的区别是,是否有执行权。
创建线程的第二种方式:
需求:简单的卖票程序,实现多个窗口同时卖票
1.定义类,实现Runnable借口
2.覆盖Runnable接口中的run方法
:将线程要运行的代码存放在run方法中
3.通过Thread类建立线程对象
4.将Runnable借口的子类对象作为实际参数传递给Thread的构造函数
:为什么要将Runnable借口的子类对象传递给Thread的构造函数?
因为自定义的run方法所属的对象是Runnable借口的子类对象,
所以要让线程去运行指定对象的run方法,就必须明确该run方法所属对象
5.调用Thread类的start方法开启线程并调用Runnable借口子类的run方法
package first; class Ticket implements Runnable{ //extends Thread{ //如果是静态的话,所有的线程会共享这100张票 /*private static int ticket =100;*/ //如果不是静态的话,每一个线程对象都会创建这个ticket对象,也即每个线程拥有100张票卖。 //这时候,如果还是采用继承Thread类的方法就不行了,需要使用实现Runnable接口创建线程 private int ticket =1000; //定义一个对象,为同步使用,任意 Object obj= new Object(); public void run() { //在这里声明的对象是无效的 /*Object obj= new Object(); */ while(true){ synchronized (obj) { if(ticket>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+".....sale : "+ ticket--); } } } } } public class TicketDemo { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); } }
实现 方式和继承方式的区别:
实现方式的好处:避免了继承方式的单继承的局限性
在定义线程时,建议使用实现方式
继承Thread的线程代码存放在Thread子类的run方法中
实现Runnable线程代码存放在借口的子类run方法中
下面有一个需求:
银行有一个金库,有两个储户分别存300元,每次存一百,存3次
package first;/* * 1.要明确哪些代码是多线程运行代码 * 2.哪些数据是共享数据 * 3.明确多线程运行代码中哪些语句是操作共享数据的 */public class BankDemo { public static void main(String[] args) { Cus cus1=new Cus(); Cus cus2=new Cus(); Thread t1=new Thread(cus1); Thread t2=new Thread(cus2); t1.start(); t2.start(); }}class Bank{ private int sum; public synchronized void add(int n,String name){//同步函数 sum+=n; System.out.println(name+" sum="+sum); }}class Cus implements Runnable{ Bank b=new Bank(); @Override public void run() { for(int i=0;i<3;i++) b.add(100,Thread.currentThread().getName()); }}
单例设计模式
//饿汉式class Single{ private static final Single s=new Single(); private Single(){} public static Single getInstance(){return s;}}//懒汉式//实例的延迟加载,但在多线程时会出错,要加锁class Single{ private static Single s=null; private Single(){} private static Single getInstance(){ if(s==null){ synchronized(Single.class){ if(s==null){ s=new Single(); } } } return s; }}
下面来一个简单的死锁程序作为结束:
死锁:简单的讲就是a需要b的资源,同时b也需要a的资源,然后两个进程就在等待,发生了死锁
package first;/* * 死锁 */public class DeadLockDemo { public static void main(String[] args) { Thread t1=new Thread(new TestDeadLock(true)); Thread t2=new Thread(new TestDeadLock(false)); t1.start(); t2.start(); }}class TestDeadLock implements Runnable{ private boolean flag; public TestDeadLock(boolean flag) { this.flag=flag; } @Override public void run() { if (flag) { synchronized (MyLock.locka) { System.out.println("if locka"); synchronized (MyLock.lockb) { System.out.println("if lockb"); } } }else{ synchronized (MyLock.lockb) { System.out.println("else lockb"); synchronized (MyLock.locka) { System.out.println("else locka"); } } } }}class MyLock{ static Object locka=new Object(); static Object lockb=new Object();}
谢谢!
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- 多线程
- ubuntu memcached安装与配置
- 3.仿微信--注册界面 布局实现
- hdu 5446 Unknown Treasure (Lucas定理+CRT+快速乘)
- Struts2.3+Spring3.2.8+Hibernate4.1全注解配置 2014-04-24 11:45:53
- 【uWSGI】 实战之操作经验
- 多线程
- word转pdf 转swf 实现在线预览word文件功能
- 解析XML格式数据文件
- 服务器安装并配置Ubuntu Server 14.04
- hive notes
- IOS Label行距间隔 首行缩进的解决
- 最全前端面试问题及答案总结
- 超实用的HTML代码段——互动出版网
- Webstorm/Phpstorm 的高效快捷键