黑马程序员———多线程和死锁问题总结
来源:互联网 发布:it培训机构知乎 编辑:程序博客网 时间:2024/05/21 17:35
------<a target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一.实现线程的两种方式:
方式一:
1.继承自Thread;
2.重写run();
3.启动:
1).实例化自定义线程的对象;
2).调用start();
class MyThread extends Thread{
public void run(){
//代码
}
}
main(){
MyThread t = new MyThread();
t.start();
}
方法二:
1.实现Runnable接口
2.重写run()方法;
3.启动:
1).实例化自定义对象;
2).实例化Thread对象,传递我们的自定义对象;
3).调用Thread的start()方法;
class MyRunnable implements Runnable{
public void run(){
//代码
}
}
main(){
MyRunnable myRun = new MyRunnable();
Thread t = new Thread(myRun);
t.start();
//写成一句话
new Thread(new MyRunnable()).start();
}
二.线程的调度:
1.休眠:sleep(long millis):
2.加入:join():调用join()的线程会保证先执行完毕,后续start()的线程会等待当前线程完成再执行;
3.礼让:yield():使当前线程退回到"就绪"状态,同其它线程站在同一起跑线上等待操作系统分配资源。
很有可能会被再次的分配到执行时间;
4.守护线程:setDaemon(true):守护线程:当主进程结束,守护线程同时结束。(不会立即,会有个小缓冲)
非守护线程:当主进程结束,非守护线程会继续执行。应用程序不会立即结束,会等待线程执行完毕;
5.中断:stop():过时:
interrupt():当线程内,处于Object--wait()或者Thread--join()或者Thread--sleep()三种阻塞状态时,会促使这种阻塞
发生异常,我们在异常处理的代码中可以结束掉当前的线程执行;
6.线程的生命周期:
新建--(start())-->就绪--(由操作系统分配)-->运行--(stop()或者interrupt()或者run()方法执行完毕)-->死亡
面试题:
1.当调用线程的start()方法后,线程就会立即运行;这句话说得不对。
三.同步:
1.当多个线程访问同一资源时,会产生"并发访问"的问题:
2."并发性访问"的判断标准:
1).是否是多线程环境
2).是否有共享数据
3).是否有多条语句操作共享数据
3.解决方法:加锁:使用关键字:synchronized
4.语法格式:
1).同步代码块:
synchronized(被锁的对象){
}
2).同步方法:
public synchronized void set(int num){
}
3.静态方法内部也可以定义同步代码块;
public static void show(){
synchronized(class对象){
}
}
4).静态方法也可以被声明为synchronized:
public synchronized static void show(){
}
例子:
<span style="font-family:KaiTi_GB2312;font-size:14px;">package cn.itcast.demo15_模拟银行账户_同步代码块和同步方法;public class Demo {public static void main(String[] args) {//1.实例化账户Accound acc = new Accound();//2.两个线程SetThread setT = new SetThread(acc);GetThread getT = new GetThread(acc);//3.启动两个线程setT.start();getT.start();//主进程为了打印最后的余额,等待1秒,保证两个线程先完成try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//打印余额System.out.println("最终余额:" + acc.getBalance());}}</span>
<span style="font-family:KaiTi_GB2312;font-size:14px;">package cn.itcast.demo15_模拟银行账户_同步代码块和同步方法;public class Accound {private int balance = 1000000;/*public void set(int num){//同步代码块synchronized (this) {//存钱this.balance += num;}}public void get(int num){//取钱的线程//同步代码块synchronized (this) {this.balance -= num;}}*///同步方法:锁的对象:当前对象,相当于 synchronized(this)public synchronized void set(int num){this.balance += num;}public synchronized void get(int num){//取钱的线程this.balance -= num;}//静态方法:内部可不可以包含synchronized代码块?OK的public static void show(){//一般静态方法中的同步代码块,不能锁:this对象。一般锁:这个类的class对象;synchronized (Accound.class) {System.out.println("show()");}}//静态方法:可不可以是synchronized的方法?OK的;public synchronized static void show2(){System.out.println("show2()");}public int getBalance(){return this.balance;}}</span>
<span style="font-family:KaiTi_GB2312;font-size:14px;">package cn.itcast.demo15_模拟银行账户_同步代码块和同步方法;public class GetThread extends Thread {private Accound accound;public GetThread(Accound acc){this.accound = acc;}@Overridepublic void run() {for(int i = 0;i < 1000 ; i++){this.accound.get(1000);}System.out.println("取钱完毕!");}}</span>
<span style="font-family:KaiTi_GB2312;font-size:14px;">package cn.itcast.demo15_模拟银行账户_同步代码块和同步方法;public class SetThread extends Thread {private Accound accound;public SetThread(Accound acc){this.accound = acc;}public void run() {for(int i = 0 ;i < 1000 ;i ++){this.accound.set(1000);}System.out.println("存钱完毕!");};}</span>
一.JDK5的Lock锁:
Lock o = .....;
o.lock();
try{
}finally{
o.unlock();
}
二.死锁问题:
1.基于同步锁,当锁定某对象时,其它对象会对此对象进行访问,在不释放锁的情况下,其它线程会一直等待;
如果双方线程都在如此等待时,这就是:死锁;
2.死锁问题的解决:见:"什么是死锁及死锁的必要条件和解决方法.doc"
三.生产消费者问题:
1.一方生产,一方消费:此例只适用于"单生产"和"单消费"的情况;
2.解决:
在共享资源内部,当资源没有准备好时,可以让当前访问的线程等待:Object-->wait();
在准备好资源后,可以唤醒等待的线程:notify():唤醒一个线程;
notifyAll():唤醒所有等待的线程;
四.线程组:
1.线程都有线程组,默认线程组:main;
2.设定线程组:
1).实例化我们的线程类;
2).实例化线程组;
3).实例化一个Thread,传递参数:线程组对象、线程对象、线程名称
MyThread myT1 = new MyThread();
ThreadGroup group = new ThreadGroup("我的线程组");
Thread t = new Thread(group,myT1,"线程1");
3.线程组的意义:
可以对多个线程进行统一管理,可以统一执行操作;例如:一次性停止线程组内的所有线程;
五.线程池:
1.JDK5之后;
2.实现方式:
1).获取线程池:
ExecutorService service = Executors.newFixedThreadPool(2);
//调用service的submit()方法
MyThread t1 = new MyThread();
Future<?> result = service.submit(t1);
//获取返回值:
Object value = result.get();
2).可以反复的运行线程池中的线程对象
service.submit(t1);
六.JDK5的线程实现方式:
1.实现Callable接口
2.重写call()方法;
3.启动:
使用线程池的方式;
特点:JDK5的线程方式可以获取返回值,并且call方法可以抛出异常;
七.定时器
1.TimerTask(抽象类):定义任务:
1).自定义类,继承自TimerTask;
2).重写run()方法;
2.Timer(类):启动定时器,执行任务;
1).实例化一个Timer();
2).public void schedule(TimerTask task, long delay):在指定的时间执行指定的任务。只执行一次。
public void schedule(TimerTask task,long delay,long period):在指定的时间,执行任务,并每隔period时间,反复的执行;
八.设计模式:
1.简单工厂模式:
2.工厂方法模式:
3.单例模式:
1).饿汉式
2).懒汉式
- 黑马程序员———多线程和死锁问题总结
- 黑马程序员:Java基础——多线程的死锁问题
- 黑马程序员 JAVASE——多线程安全(并发问题和死锁等)
- 黑马程序员——多线程5:死锁
- 【黑马程序员】java多线程同步不安全问题,锁和死锁等总结
- 黑马程序员——Java基础——多线程的同步、死锁和等待唤醒机制
- 黑马程序员——java多线程之死锁和等待唤醒机制
- 黑马程序员——死锁
- 黑马程序员 多线程死锁的问题.
- 黑马程序员-多线程死锁
- 黑马程序员——java多线中的死锁问题
- 黑马程序员——多线程知识总结
- 黑马程序员——多线程问题
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- android布局 —— LinearLayout
- Linux的fdisk命令详解
- mysql笔记
- poj 2481(树状数组)
- 1505: 酷酷的单词
- 黑马程序员———多线程和死锁问题总结
- NEUQ 1420: Problem A - Y2K Accounting Bug
- Knowledge Generation Model for Visual Analytics
- DP经典问题:多米诺骨牌(TYVJ 2199, COGS 1205)
- 奋斗假分页
- JS登陆与注册验证
- C++对象模型——解构语意学(第五章)
- kafka0.8.2以下版本删除topic
- 深度学习文献阅读笔记(2)