JAVA--多线程(很重要的呀)
2015-07-17 22:02
441 查看
什么是进程
概念: 正在运行的程序,所占用的内存的空间资源
什么是线程
概述: 线程就是对于CPU的一条独立的执行路径
看成是一个进程中的,多个小程序的独立执行
实现多线程的第一种方式
线程这个事物,也被封装成对象.线程对象的描述类
java.lang.Thread
实现创建新线程步骤
定义类,继承Thread
重写Thread类run方法
创建Thread子类对象
调用的是Thread类的方法start
实现多线程第二种方式
实现接口方式 java.lang.Runnable
实现步骤
定义类,实现Runnable接口
重写抽象方法run
创建Thread类对象 ,在Thread类的构造方法中,
传递Runnable接口实现类对象
调用Thread类方法start
5 实现线程的两种方式对比
继承Thread
实现Runnable接口
继承Thread,单继承
继承的方式,线程中数据被单个线程独享
实现接口方式,避免了单继承局限性
实现方式,线程中的数据被线程共享
6 同步技术
出现目的,解决线程操作共享数据的安全问题
关键字 synchronized
格式:
synchronized(任意对象){
线程操作的所有共享数据
}
平衡,速度和安全上,保证安全,牺牲速度
任意对象: 监视器 –> 同步锁 – > 锁
线程运行到同步代码块的时候,先判断,判断这个锁还有没有
如果没有,只能等在外面
如果这个所有,有,线程就获取到这个对象锁,进入同步运行
线程出去同步代码块后,对象锁在交还回去
没有锁的线程,不能进入同步执行
上列子~~!
死锁
多个线程,抢夺同一个对象锁,造成程序假死现象
线程通信
所有的线程,操作的共享数据,必须都同步
必须保证所有的同步使用的锁,唯一的
线程通信中的等待与唤醒机制
生产者生产完成后,需要等待,等待之前唤醒消费者线程
消费者线程打印完后,需要等待,等待之前唤醒生产者线程
程序加了线程的等待和唤醒 Object类的方法 wait notify
抛出 IllegalMonitorStateException异常
无效的监视器状态异常
wait notify 必须有锁的支持
只有锁对象才能调用
这个线程通信中包含了一个唤醒等待机制
线程中的一些小知识点(别小看哦)
为什么wait(),notify(),notifyAll()等方法都定义在Object类中
操作线程的,Thread,为什么不写在Thread类中,出现在Object类中
锁的问题,锁是任意对象,等待还是唤醒必须有锁的支持,只有锁对象才能调用
方法写了最顶层的父类中,任何子类对象,当作锁,都可以调用线程的方法了
Thread类方法sleep 和 Object方法wait有什么区别
sleep 不会释放对象锁
wait 释放对象锁,被唤醒,从新获取锁才能运行
线程池
池技术 pool
有些操作,非常耗时好资源
创建新的线程
JAVA连接数据库服务器
程序开始的时候,创建出锁需要的线程,创建只有1次
容器中保存起来,从容器取出,运行完成后,线程不死,继续回到容器中等待
集合容器
ArrayList
add(t0);
add(t0);
add(t0);
Thread t =array. remove(0);
t.start();
add(t);
JDK5版本,添加使用线程池的功能,内置线程池的概念
工厂类, 负责创建需要的对象
Executors 类负责创建线程池的对象
全部都是静态方法,类名调用
static ExecutorService newCachedThreadPool() 创建新的线程池对象
返回的肯定是接口ExecutorService实现类的对象
static ExecutorService newFixedThreadPool(int nThreads) 创建新的线程池对象,传递int参数
线程池就有指定的线程个数
static ExecutorService newSingleThreadExecutor() 创建线程池对象,池子里面只有1个线程
等同于newFixedThreadPool(1)
ExecutorService 接口方法
submit(Runnable task) 用于执行线程池中的线程,线程去运行Runnable接口实现类的run方法
void run(){
}
Future 获取线程执行后的返回值
Future
submit(Callable task) 用于执行线程池中的线程,运行的是Callable接口的实现类的方法
实现线程的第三种方式
java.util.concurrent.Callable
实现Callable接口,重写call方法
call可以有返回值,可以抛出异常
第三种方式,出现的版本1.5
不要和Thread,Runnable,Callable只能作用在线程池里
Future submit(Callable call)传递Callable接口实现类的对象
submit方法执行完毕后,可以获取到线程运行后的返回值
返回的是Future接口的实现类对象
Future接口方法 get 可以获取到线程执行后的返回值结果
单例设计模式Single
实现思想: 保证一个类的对象,在内存中唯一性
这个是个很有趣的东西~~!
先来个饿汉式的~~!
再来个懒汉的~~!
然后就是一下线程的方法~~!
* Thread类的方法 setDaemon(boolean )true
* 线程标记为守护线程,必须在start之前使用
* 所有的线程,都是守护线程的时候JVM,就退出
*
* Thread类的方法 static yield 线程的让步
* * 等待该线程终止
*
* Thread类 join
* 执行join方法的线程,会一次性执行完毕
* 其他线程,等我执行完后,抢CPU资源
* Thread类的静态的方法sleep(long 毫秒值)
* 让执行的线程,在指定的毫秒内,休眠,时间到了,自己醒来继续执行
这个方法要自己try —catch ~~
线程的优先级
* 每个线程都有自己的优先级 1-10
* Thread类方法 int getPriority() 获取线程的优先级
* 优先级高,在用CPU的时间相对更多一些
*
* setPriority(int newPriority) 设置线程的优先级
* Thread类中,提供三个静态成员变量,说明优先级
如何获取,设置线程的名字
每个线程都有自己的名字
Thread-0 -1 -2
获取线程名字
Thread类方法 String getName()
在Thread类用,在Thread子类使用
Thread类,有一个静态方法 currentThread()
返回当前正在运行的线程对象 Thread currentThread()
继续使用线程对象,调用getName方法获取名字
设置线程名字
Thread类的方法 void setName(String name)设置线程名字
Thread类的构造方法(String name)
JDK5新特性,实现线程的加锁和释放锁
java.util.concurrent.locks
接口Lock 实现类ReentrantLock
替代了同步代码块,同步方法的使用
接口方法: lock 获取锁 unlock释放锁
终止线程的2个方式
第一个方式 stop 过时
第二个方式 结束run就可以
void interrupt() 中断线程
比喻:
线程 ->wait永久等待,没有任何线程唤醒你
interrupt让等待线程停止
以上方法不分顺序~
还有线程池 线程组!
*Thread类的方法 ThreadGroup getThreadGroup()
*获取线程组对象,返回值是ThreadGroup类的对象
*ThreadGroup类方法 String getName()组的名字
*
*ThreadGroup对线程进行分组管理
* 分组管理一起对一个组中的线程进行统一的设置
*
*ThreadGroup构造方法 传递字符串的组的名字
* 可以自己定义组名,传递给ThreadGroup类构造方法
*
*如何把线程放在线程组中
*Thread类构造方法 第一个参数传递的是线程组的对象
*第二个参数,传递的Runnable接口的实现类对象
使用JDK5新特性,创建线程池,并且让线程运行起来
使用Executors静态方法创建线程池对象
ExecutorService接口方法 submit执行线程
submit(Runnable)
线程这个只是点实在是太乱了~~总结的不好 多多包涵
概念: 正在运行的程序,所占用的内存的空间资源
什么是线程
概述: 线程就是对于CPU的一条独立的执行路径
看成是一个进程中的,多个小程序的独立执行
实现多线程的第一种方式
线程这个事物,也被封装成对象.线程对象的描述类
java.lang.Thread
实现创建新线程步骤
定义类,继承Thread
重写Thread类run方法
创建Thread子类对象
调用的是Thread类的方法start
/* * 创建新的执行线程 * 定义类继承Thread * 重写run方法 * new Thread子类对象 * 调用父类方法start() * start 开启线程 * JVM调用run * 规范,不管让线程运行什么,请把代码写在run中 */ class SubThread extends Thread{ public void run(){ for(int x = 0 ; x < 50 ;x++){ System.out.println("run.."+x); } } } public class ThreadDemo { public static void main(String[] args) { SubThread s = new SubThread(); s.start(); for(int x = 0 ; x < 50 ;x++){ System.out.println("main.."+x); } } }
实现多线程第二种方式
实现接口方式 java.lang.Runnable
实现步骤
定义类,实现Runnable接口
重写抽象方法run
创建Thread类对象 ,在Thread类的构造方法中,
传递Runnable接口实现类对象
调用Thread类方法start
/*创建新的执行线程 * 定义类实现接口Runnable * 重写run方法 * new 实现接口类对象 * 创建Thread类对象,传递Runnable实现类 * 调用父类方法start() * start 开启线程 * JVM调用run * 规范,不管让线程运行什么,请把代码写在run中 */ public class RunnableDemo { public static void main(String[] args) { // new 实现接口类对象 RunnableIterface r = new RunnableIterface(); //创建Thread类对象,传递Runnable实现类 Thread t1 = new Thread(r); Thread t2 = new Thread(r); Thread t3 = new Thread(r); //调用父类方法start() t1.start(); t2.start(); t3.start(); } } class RunnableIterface implements Runnable{ //定义类实现接口Runnable public void run() {//重写run方法 System.out.println(Thread.currentThread().getName()+"第二种线程方法~~"); } }
5 实现线程的两种方式对比
继承Thread
实现Runnable接口
继承Thread,单继承
继承的方式,线程中数据被单个线程独享
实现接口方式,避免了单继承局限性
实现方式,线程中的数据被线程共享
6 同步技术
出现目的,解决线程操作共享数据的安全问题
关键字 synchronized
格式:
synchronized(任意对象){
线程操作的所有共享数据
}
平衡,速度和安全上,保证安全,牺牲速度
任意对象: 监视器 –> 同步锁 – > 锁
线程运行到同步代码块的时候,先判断,判断这个锁还有没有
如果没有,只能等在外面
如果这个所有,有,线程就获取到这个对象锁,进入同步运行
线程出去同步代码块后,对象锁在交还回去
没有锁的线程,不能进入同步执行
上列子~~!
/* * 要求: * 多线程技术,模拟储户在银行存钱 * 每次存储100元,分别在两个窗口存,每个窗口存3次 * 余额是0 * 存储的时候余额变化 * 100 200 300 400 500 600 * 一个是银行 存钱的功能 * 一个储户,调用银行的存钱功能,参数 * * 方法add 代码全是线程共享数据 * 同步整个方法 synchronized加在方法的声明上 * * 同步方法,同步函数,同步方法只能被一个线程调用,不调用完成,其他线程不能调用 * 同步方法有锁吗,肯定有锁 , 本类对象引用 this * * 静态同步方法中,肯定也有锁,锁是谁呢,锁必须是对象 * 对象就是自己类的 class文件 被JVM创建出来的这个对象 * * 任何一个数据类型 ,JVM都会赋予他一个特别的属性 属性名字 class * 静态方法中的同步锁,就是自己本类.class属性 */ class Bank{ private static int sum = 0; //private Object obj = new Object(); public static synchronized void add(int money){ //synchronized(Bank.class){ sum = sum + money; System.out.println(sum); //} } } class Customer implements Runnable{ private Bank b = new Bank(); public void run(){ for(int x = 0 ; x < 3 ; x++){ b.add(100); } } } public class ThreadDemo9 { public static void main(String[] args) { Customer c = new Customer(); Thread t0 = new Thread(c); Thread t1 = new Thread(c); t0.start(); t1.start(); } }
死锁
多个线程,抢夺同一个对象锁,造成程序假死现象
/* * 多线程,争夺同一个对象锁资源,出现的假死 * 同步的嵌套技术实现 */ //定义类,实现同步的嵌套 class Dead implements Runnable{ private boolean b; Dead(boolean b){this.b=b;} public void run(){ while(true){ //对变量b进行判断,如果b=true,同步嵌套 //线程先进入同步A锁,在进入同步B锁 if(b){ synchronized(LockA.locka){ System.out.println("if...locka"); synchronized(LockB.lockb){ System.out.println("if...lockb"); } } } //变量的值b=false,同步嵌套 //线程先进入同步B锁,在进同步A锁 else{ synchronized(LockB.lockb){ System.out.println("else...lockb"); e8c6 synchronized(LockA.locka){ System.out.println("else...locka"); } } } } } } public class ThreadDead { public static void main(String[] args) { Dead d1 = new Dead(true); Dead d2 = new Dead(false); Thread t1 = new Thread(d1); Thread t2 = new Thread(d2); t1.start(); t2.start(); } } //创建2个类,2个类的对象,作为锁使用 class LockA{ public static final LockA locka = new LockA(); } class LockB{ public static final LockB lockb = new LockB(); }
线程通信
所有的线程,操作的共享数据,必须都同步
必须保证所有的同步使用的锁,唯一的
线程通信中的等待与唤醒机制
生产者生产完成后,需要等待,等待之前唤醒消费者线程
消费者线程打印完后,需要等待,等待之前唤醒生产者线程
程序加了线程的等待和唤醒 Object类的方法 wait notify
抛出 IllegalMonitorStateException异常
无效的监视器状态异常
wait notify 必须有锁的支持
只有锁对象才能调用
/* * 线程的通信 * 多线程针对同一个学生资源,采用不同类型的数据操作 * 一个线程,负责对学生资源的复制,另一个线程对学生资源负责打印值 */ //定义学生类,资源对象,姓名,姓别成员即可 class Student { String name; String sex; boolean flag ; } //定义生产者线程,负责对学生赋值 class Product implements Runnable{ private Student s ; Product(Student s){this.s=s;} public void run(){ int x = 0 ; while(true){ synchronized(s){ //判断标记 if(s.flag){ try{s.wait();}catch(Exception ex){} } if(x%2==0){ s.name = "张三"; s.sex = "男"; }else{ s.name = "李四"; s.sex = "女"; } x++; //修改标记的值 s.flag = true; //唤醒消费线程 s.notify(); } } } } //定义消费者线程,负责学生变成获取值 class Customer implements Runnable{ private Student s; Customer(Student s){this.s=s;}; public void run(){ while(true){ synchronized(s){ //判断标记 if(!s.flag){ try{s.wait();}catch(Exception ex){} } System.out.println(s.name+"..."+s.sex); //修改变量的值 s.flag=false; //唤醒生产线程 s.notify(); } } } } public class ThreadDemo { public static void main(String[] args) { Student s = new Student(); //创建2个Runnable接口实现类 Product p = new Product(s); Customer c = new Customer(s); Thread t0 = new Thread(p); Thread t1 = new Thread(c); t0.start(); t1.start(); } }
这个线程通信中包含了一个唤醒等待机制
线程中的一些小知识点(别小看哦)
为什么wait(),notify(),notifyAll()等方法都定义在Object类中
操作线程的,Thread,为什么不写在Thread类中,出现在Object类中
锁的问题,锁是任意对象,等待还是唤醒必须有锁的支持,只有锁对象才能调用
方法写了最顶层的父类中,任何子类对象,当作锁,都可以调用线程的方法了
Thread类方法sleep 和 Object方法wait有什么区别
sleep 不会释放对象锁
wait 释放对象锁,被唤醒,从新获取锁才能运行
线程池
池技术 pool
有些操作,非常耗时好资源
创建新的线程
JAVA连接数据库服务器
程序开始的时候,创建出锁需要的线程,创建只有1次
容器中保存起来,从容器取出,运行完成后,线程不死,继续回到容器中等待
集合容器
ArrayList
add(t0);
add(t0);
add(t0);
Thread t =array. remove(0);
t.start();
add(t);
JDK5版本,添加使用线程池的功能,内置线程池的概念
工厂类, 负责创建需要的对象
Executors 类负责创建线程池的对象
全部都是静态方法,类名调用
static ExecutorService newCachedThreadPool() 创建新的线程池对象
返回的肯定是接口ExecutorService实现类的对象
static ExecutorService newFixedThreadPool(int nThreads) 创建新的线程池对象,传递int参数
线程池就有指定的线程个数
static ExecutorService newSingleThreadExecutor() 创建线程池对象,池子里面只有1个线程
等同于newFixedThreadPool(1)
ExecutorService 接口方法
submit(Runnable task) 用于执行线程池中的线程,线程去运行Runnable接口实现类的run方法
void run(){
}
Future 获取线程执行后的返回值
Future
submit(Callable task) 用于执行线程池中的线程,运行的是Callable接口的实现类的方法
/* * 使用JDK5新特性,创建线程池,并且让线程运行起来 * 1. 使用Executors静态方法创建线程池对象 * 2. ExecutorService接口方法 submit执行线程 * submit(Runnable) * */ class RunnableImpl implements Runnable{ public void run(){ System.out.println(Thread.currentThread().getName()); } } public class ThreadPoolDemo { public static void main(String[] args) { //使用Executors静态方法创建线程池对象,2个线程的池子 ExecutorService es = Executors.newFixedThreadPool(2); //调用接口方法submit 传递Runnable接口实现类 es.submit(new RunnableImpl()); es.submit(new RunnableImpl()); //关闭线程池 es.shutdown(); } }
实现线程的第三种方式
java.util.concurrent.Callable
实现Callable接口,重写call方法
call可以有返回值,可以抛出异常
第三种方式,出现的版本1.5
不要和Thread,Runnable,Callable只能作用在线程池里
Future submit(Callable call)传递Callable接口实现类的对象
submit方法执行完毕后,可以获取到线程运行后的返回值
返回的是Future接口的实现类对象
Future接口方法 get 可以获取到线程执行后的返回值结果
/* * 实现线程的第三种方式,结合线程池使用 * 线程运行后的结果 */ //定义类,实现Callable,重写call方法 class CallableImpl implements Callable<String>{ public String call()throws Exception{ System.out.println("执行了call方法"); return "abc"; } } public class ThreadPoolDemo1 { public static void main(String[] args)throws Exception { //Executors 静态方法创建线程池 ExecutorService es = Executors.newFixedThreadPool(1); //ExecutorService方法submit运行线程 //submit方法,返回Future接口实现类对象 Future<String> f = es.submit(new CallableImpl()); String s = f.get(); System.out.println(s); es.shutdown(); } }
单例设计模式Single
实现思想: 保证一个类的对象,在内存中唯一性
这个是个很有趣的东西~~!
先来个饿汉式的~~!
/* * 保证Single类,的对象在内存中是唯一性 * 私有构造方法 * 创建对象,是要调用构造方法 * 本类成员位置,创建自己类的对象 * 提供公共访问方式,外类获取对象 * * 以下写法,成为单例模式 -- 饿汉式 * */ public class Single { private Single(){} private static Single s = new Single(); public static Single getInstance(){ return s; } }
再来个懒汉的~~!
/* * 保证Single类的对象,在内存中的唯一性 * 懒汉式,对象的延迟加载 * 利用同步保证数据安全,利用双重if判断,提升程序的执行效率 */ public class Single { private Single() { } private static Single s = null; public static Single getInstance() { if (s == null) { synchronized (Single.class) { if (s == null)//这个if是绝对绝对不可以去掉 s = new Single(); } } return s; } }
然后就是一下线程的方法~~!
* Thread类的方法 setDaemon(boolean )true
* 线程标记为守护线程,必须在start之前使用
* 所有的线程,都是守护线程的时候JVM,就退出
*
* Thread类的方法 static yield 线程的让步
* * 等待该线程终止
*
* Thread类 join
* 执行join方法的线程,会一次性执行完毕
* 其他线程,等我执行完后,抢CPU资源
* 线程的控制方法
* Thread类的静态的方法sleep(long 毫秒值)
* 让执行的线程,在指定的毫秒内,休眠,时间到了,自己醒来继续执行
这个方法要自己try —catch ~~
线程的优先级
* 每个线程都有自己的优先级 1-10
* Thread类方法 int getPriority() 获取线程的优先级
* 优先级高,在用CPU的时间相对更多一些
*
* setPriority(int newPriority) 设置线程的优先级
* Thread类中,提供三个静态成员变量,说明优先级
如何获取,设置线程的名字
每个线程都有自己的名字
Thread-0 -1 -2
获取线程名字
Thread类方法 String getName()
在Thread类用,在Thread子类使用
Thread类,有一个静态方法 currentThread()
返回当前正在运行的线程对象 Thread currentThread()
继续使用线程对象,调用getName方法获取名字
设置线程名字
Thread类的方法 void setName(String name)设置线程名字
Thread类的构造方法(String name)
JDK5新特性,实现线程的加锁和释放锁
java.util.concurrent.locks
接口Lock 实现类ReentrantLock
替代了同步代码块,同步方法的使用
接口方法: lock 获取锁 unlock释放锁
终止线程的2个方式
第一个方式 stop 过时
第二个方式 结束run就可以
void interrupt() 中断线程
比喻:
线程 ->wait永久等待,没有任何线程唤醒你
interrupt让等待线程停止
class Stop implements Runnable{ private boolean flag = true; public void run(){ while(flag){ synchronized(this){ try{this.wait();} catch(Exception ex){ ex.printStackTrace(); System.out.println("抓住异常"); flag = false; } System.out.println("run..."); } } } public void setFlag(boolean flag){ this.flag =flag; } } public class ThreadStop { public static void main(String[] args)throws Exception { Stop s = new Stop(); Thread t0 = new Thread(s); t0.start(); Thread.sleep(5); t0.interrupt(); // s.setFlag(false); } }
以上方法不分顺序~
还有线程池 线程组!
*Thread类的方法 ThreadGroup getThreadGroup()
*获取线程组对象,返回值是ThreadGroup类的对象
*ThreadGroup类方法 String getName()组的名字
*
*ThreadGroup对线程进行分组管理
* 分组管理一起对一个组中的线程进行统一的设置
*
*ThreadGroup构造方法 传递字符串的组的名字
* 可以自己定义组名,传递给ThreadGroup类构造方法
*
*如何把线程放在线程组中
*Thread类构造方法 第一个参数传递的是线程组的对象
*第二个参数,传递的Runnable接口的实现类对象
使用JDK5新特性,创建线程池,并且让线程运行起来
使用Executors静态方法创建线程池对象
ExecutorService接口方法 submit执行线程
submit(Runnable)
线程这个只是点实在是太乱了~~总结的不好 多多包涵
相关文章推荐
- Java基础
- 使用Eclipse构建Maven的SpringMVC项目
- Java中流的分类
- Java学习之static关键字(下)
- [LeetCode][Java] Set Matrix Zeroes
- java回调机制学习
- [JDK]什么是JDK
- 内存大小设置 Java heap space错误
- 提高Java代码质量的Eclipse插件之Checkstyle的使用详解
- 提高Java代码质量的Eclipse插件之Checkstyle的使用详解
- Maven-Mac-Java
- 【记录】使用eclipse遇到的问题一:eclipse中按空格/Tab键错误触发代码补全
- Java基础深入解析——类与对象
- Ubuntu14.04安装JDK与配置环境变
- Java基础深入解析——类与对象
- Java中的HashCode方法
- Spring Mobile 与struts整合
- javaweb新建helloworld项目
- Java_LIST使用方法和四种遍历arrayList方法
- 在Editplus中配置java的(带包)编译(javac)和运行(java)的方法