Java多线程的学习
来源:互联网 发布:java编写图书管理系统 编辑:程序博客网 时间:2024/06/05 04:35
Java多线程学习
进程:正在执行的程序,有一个执行顺序,顺序是一个执行路径, 或者叫控制单元
线程:进程中独立的控制单元,至少有一个
JAVA vm 启动时有一个进程java.exe
至少有一个线程存在main函数中叫主线程。
jvm 启动不只一个线程,还有负责垃圾回收处理机制的线程。
java.lang.Thread
- 创建线程第一种方式是继承Thread
- 并复写run()方法(目的是将自定义的代码存储在run()方法中)
- 调用改线程的start()方法(因为对象.run()仅仅是调用方法,线程创建了,并没有运行)
多线程具有随机性
多个线程获取cpu的执行权,每一个时间只能一个程序占用cpu(多核除外)
- 几种状态sleep(),wait(),notify(),stop(),和一个特殊状态:阻塞–具备运行资格,但没有执行权
-
线程名称
默认名称为Thread-编号
.getName()获得线程名称,.setName()设置线程名称,Thread.currentThread()获得当前线程
java.lang.Runnable接口
- 创建线程第二种方式 实现Runnable方法
- 覆盖Runnable接口的run方法
- 通过Thread类建立线程对象
- 将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
- 调用Thread类的static方法开启线程并调用Runnable接口子类的run方法
实现相比第一种方式的好处: Runnable避免了单继承的局限性,在定义线程时,尽量使用接口实现的方式。
区别:继承线程代码存放在Thread子类的run方法中
实现Runnable线程代码存放在接口子类的run方法中
class Ticket implements Runnable{ public void run(){ //do something }}class Demo{ public static void main(String[] args) { Ticket t= new Ticket(); Thread t1=new Thread(t); Thread t2=new Thread(t); t1.start(); t1.start(); }}
多线程安全问题
–1.使用同步代码块
synchronized(对象){ //需要被同步的代码块 //只能有一个线程进入,执行完之后才能进下一个进程}
好处:解决了多线程的安全问题
弊端:多个线程都需要判断锁,较为消耗资源
–2.同步函数
public synchronized void show(){ //do something}
- 同步函数使用的锁是哪一个?
–函数需要被对象调用,那函数都有一个所属对象的引用,就是this。 - 如果同步函数被静态修饰后用的锁不是this,尤为静态方法中没有this
- 静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。类名.class 该类的类型是Class(静态同步方法)
synchronized(类名.class){ //需要被同步的代码块}public static synchronized void show(){ //do something}
–3.防止死锁
多线程使用同一个锁,防止互相嵌套
class Ticket implements Runnable{ private int num = 100; Object obj = new Object(); boolean flag = true; public void run() { if(flag) while(true) { synchronized(obj) { show(); } } else while(true) this.show(); } public synchronized void show() { synchronized(obj) { if(num>0) { try{Thread.sleep(10);}catch (InterruptedException e){} System.out.println(Thread.currentThread().getName()+".....sale...."+num--); } } }}class DeadLockDemo { public static void main(String[] args) { Ticket t = new Ticket();// System.out.println("t:"+t); Thread t1 = new Thread(t); Thread t2 = new Thread(t); t1.start(); try{Thread.sleep(10);}catch(InterruptedException e){} t.flag = false; t2.start(); }}
线程间通信
–多个线程操作统一资源,但操作动作不同
等待唤醒机制
–涉及的方法:
1,wait(): 让线程处于冻结状态,被wait的线程会被存储到线程池中。
2,notify():唤醒线程池中一个线程(任意).
3,notifyAll():唤醒线程池中的所有线程。
这些方法都必须定义在同步中。
因为这些方法是用于操作线程状态的方法。
必须要明确到底操作的是哪个锁上的线程。
为什么操作线程的方法wait notify notifyAll定义在了Object类中?
因为这些方法是监视器的方法。监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
class Resource{ private String name; private String sex; private boolean flag = false; public synchronized void set(String name,String sex) { if(flag) try{this.wait();}catch(InterruptedException e){} this.name = name; this.sex = sex; flag = true; this.notify(); } public synchronized void out() { if(!flag) try{this.wait();}catch(InterruptedException e){} System.out.println(name+"...+...."+sex); flag = false; notify(); }}//输入class Input implements Runnable{ Resource r ;// Object obj = new Object(); Input(Resource r) { this.r = r; } public void run() { int x = 0; while(true) { if(x==0) { r.set("mike","nan"); } else { r.set("丽丽","女女女女女女"); } x = (x+1)%2; } }}//输出class Output implements Runnable{ Resource r;// Object obj = new Object(); Output(Resource r) { this.r = r; } public void run() { while(true) { r.out(); } }}class ResourceDemo3{ public static void main(String[] args) { //创建资源。 Resource r = new Resource(); //创建任务。 Input in = new Input(r); Output out = new Output(r); //创建线程,执行路径。 Thread t1 = new Thread(in); Thread t2 = new Thread(out); //开启线程 t1.start(); t2.start(); }}
多于两个线程的进程间通信
–自我理解:将两个线程的if(flag)改为while(flag)【让唤醒的线程再一次判断标记】,notify()改为notifyAll()【notify()可能只会唤醒本方线程(导致所有线程等待)】
notify()往往唤醒的是线程池中的第一个,所以用flag标记和notifyAll()配合使用解决。
JDK1.5后新特性lock
–jdk1.5以后将同步和锁封装成了对象。
并将操作锁的隐式方式定义到了该对象中,
将隐式动作变成了显示动作。
Lock接口(替代synchronized): 出现替代了同步代码块或者同步函数。
将同步的隐式锁操作变成现实锁操作。同时更为灵活。可以一个锁上加上多组监视器。
Condition接口:出现替代了Object中的wait notify notifyAll方法。
将这些监视器方法单独进行了封装,变成Condition监视器对象。可以使用多个condition与任意锁进行组合。
lock();//获取锁。unlock();//释放锁,通常需要定义finally代码块中。await();//替代wait()signal();//替代notify();signalAll();//替代notifyAll();
import java.util.concurrent.locks.*;class Resource{ private String name; private int count = 1; private boolean flag = false;// 创建一个锁对象。 Lock lock = new ReentrantLock(); //通过已有的锁获取该锁上的监视器对象。// Condition con = lock.newCondition(); //通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者。 Condition producer_con = lock.newCondition(); Condition consumer_con = lock.newCondition(); public void set(String name)// t0 t1 { lock.lock(); try { while(flag)// try{lock.wait();}catch(InterruptedException e){}// t1 t0 try{producer_con.await();}catch(InterruptedException e){}// t1 t0 this.name = name + count;//烤鸭1 烤鸭2 烤鸭3 count++;//2 3 4 System.out.println(Thread.currentThread().getName()+"...生产者5.0..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3 flag = true;// notifyAll();// con.signalAll(); consumer_con.signal(); } finally { lock.unlock();//finally用来释放资源 } } public void out()// t2 t3 { lock.lock(); try { while(!flag)// try{this.wait();}catch(InterruptedException e){} //t2 t3 try{cousumer_con.await();}catch(InterruptedException e){} //t2 t3 System.out.println(Thread.currentThread().getName()+"...消费者.5.0......."+this.name);//消费烤鸭1 flag = false;// notifyAll();// con.signalAll(); producer_con.signal(); } finally { lock.unlock(); } }}class Producer implements Runnable{ private Resource r; Producer(Resource r) { this.r = r; } public void run() { while(true) { r.set("烤鸭"); } }}class Consumer implements Runnable{ private Resource r; Consumer(Resource r) { this.r = r; } public void run() { while(true) { r.out(); } }}class ProducerConsumerDemo2{ public static void main(String[] args) { Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t0 = new Thread(pro); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); Thread t3 = new Thread(con); t0.start(); t1.start(); t2.start(); t3.start(); }}
多线程总结
1,进程和线程的概念。
|--进程:|--线程:
2,jvm中的多线程体现。
|--主线程,垃圾回收线程,自定义线程。以及他们运行的代码的位置。
3,什么时候使用多线程,多线程的好处是什么?创建线程的目的?
|--当需要多部分代码同时执行的时候,可以使用。
4,创建线程的两种方式。★★★★★
|--继承Thread |--步骤|--实现Runnable |--步骤|--两种方式的区别?
5,线程的5种状态。
对于执行资格和执行权在状态中的具体特点。|--被创建:|--运行:|--冻结:|--临时阻塞:|--消亡:
6,线程的安全问题。★★★★★
|--安全问题的原因:|--解决的思想:|--解决的体现:synchronized|--同步的前提:但是加上同步还出现安全问题,就需要用前提来思考。|--同步的两种表现方法和区别:|--同步的好处和弊端:|--单例的懒汉式。|--死锁。
7,线程间的通信。等待/唤醒机制。
|--概念:多个线程,不同任务,处理同一资源。 |--等待唤醒机制。使用了锁上的 wait notify notifyAll. ★★★★★|--生产者/消费者的问题。并多生产和多消费的问题。 while判断标记。用notifyAll唤醒对方。 ★★★★★|--JDK1.5以后出现了更好的方案,★★★ Lock接口替代了synchronized Condition接口替代了Object中的监视方法,并将监视器方法封装成了Condition 和以前不同的是,以前一个锁上只能有一组监视器方法。现在,一个Lock锁上可以多组监视器方法对象。 可以实现一组负责生产者,一组负责消费者。 |--wait和sleep的区别。★★★★★
8,停止线程的方式。
|--原理:.interrupt()//将线程从冻结状态强制恢复到运行状态中来|--表现:--中断。
9,线程常见的一些方法。
|--.setDaemon(true)//后台进程,主线程结束后自动结束|--.join();//获取cpu执行权,此时主线程冻结至该线程结束|--.setPriority(Thread.MAX_PRIORITY);//设定优先级|--.yield();//释放执行权,不常用|--在开发时,可以使用匿名内部类来完成局部的路径开辟。
- Java多线程的学习
- java多线程的学习
- Java多线程的学习
- Java多线程的学习
- Java多线程的学习
- 【java多线程学习】多线程的基本概念
- 【java多线程学习】多线程的同步
- Java多线程和多线程计数器的学习
- java 学习-----多线程的安全问题
- 【Java多线程】的学习总结
- 学习JAVA多线程的网站
- [Thinking in JAVA] JAVA多线程的学习
- 【Java重新学习】Java多线程-多线程的创建
- Java多线程学习与Java多线程的简单应用
- java多线程学习一:实现多线程的两种方法
- java多线程学习笔记(一)!更好的理解多线程
- 多线程编程学习一(Java多线程的基础)
- 多线程编程学习一(Java多线程的基础)
- 模拟退火算法
- eight 皇后
- javascript中预编译与执行过程详解
- HTTP协议详解
- java经典算法2_判断素数
- Java多线程的学习
- Java中finally语句块的深度解析(try catch finally的执行顺序)
- (最新)关于CocoaPods安装和使用
- SQL学习整理(二)检索数据
- javascript中canvas绘图的基本用法
- POJ3617 Best Cow Line
- 遮盖层加弹出框页面布局不影响
- mac下的pycharm可能遇到的问题
- 实体小三角-制作方法