java多线程-学习总结
来源:互联网 发布:贵州省政法委数据维稳 编辑:程序博客网 时间:2024/06/05 15:26
什么是程序
安装在磁盘上的一段指令集合,它是静态的概念
什么是进程
它是运行中的程序,是动态的概念。每个进程有独立的资源空间
什么是线程
线程,又称轻量级进程,是程序执行流的最小单位,是程序中一个单一的顺序控制流程。线程是进程中的一个实体,是被系统独立调度和分派的基本单位
什么是多线程
多线程则指的是在单个程序中可以同时运行多个不同的线程执行不同的任务
多线程的特点
一个进程可以包含一个或多个线程
一个程序实现多个代码同时交替运行就需要产生多个线程
线程本身不拥有系统资源,与同属一个进程的其他线程的其他线程共享所在进程所拥有的资源
同一进程中的多个线程之间可以并发执行。cpu会随机抽出时间,让我们的程序一会做这件事情,一会做另外一件事情
多线程的目的
就是”最大限度地利用cpu资源”,当某一线程的处理不需要占用cpu而只和I/O等资源打交道时,让需要占用cpu资源的其他线程有机会获得cpu资源。从根本上说,这就是多线程编程的最终目的。
Java运行系统很多方面依赖于线程,所有的类库设计都考虑到多线程。Java是纯面向对象语言,Java的线程模型也是面向对象的
通过继承Thread类创建线程
继承Thread并重写run方法
package com.hgaong.threadtest;public class HelloThreadDemo { public static void main(String[] args) { HelloThread hT1=new HelloThread(); HelloThread hT2=new HelloThread("线程2"); hT1.setName("线程1");//设置线程名字 hT1.start();//启动线程 hT2.start(); }}class HelloThread extends Thread{ @Override public void run() { for(int i=0;i<5;i++){ System.out.println(this.getName()+":"+i); } } public HelloThread(String name){ super(name); } public HelloThread() { super(); }}
实现Runnable接口创建线程
实现Runnable接口的类必须借助Thread类才能创建线程。通过Runnable接口创建线程分为两步:
创建实现Runnable接口的类的实例
创建一个Thread类对象,将第一步实例化得到的Runnable对象作为参数传入Thread类的构造方法
通过Thread类的start方法启动线程
package com.hgaong.threadtest;//实现Runnable接口创建线程的好处//1.避免单继承的局限,一个类可以实现多个接口,但只能继承一个类//2.适合资源的共享public class HelloRunnableDemo { public static void main(String[] args) { HelloRunnable helloRunnable=new HelloRunnable(); Thread t1=new Thread(helloRunnable,"线程1"); Thread t2=new Thread(helloRunnable); t2.setName("线程2"); t1.start(); t2.start(); }}class HelloRunnable implements Runnable{ @Override public void run() { for(int i=0;i<5;i++){ //调用Thread类中的静态方法获得当前线程的引用 System.out.println(Thread.currentThread().getName()+":"+i); } }}
资源共享
package com.hgaong.threadtest;//注释部分的两个线程会各自卖5张票,不能资源共享//实现Runnable可以资源共享,一共卖掉5张票public class SharedDataThreadDemo { public static void main(String[] args) {// TicketThread tT1=new TicketThread("一号窗口");// TicketThread tT2=new TicketThread("二号窗口");// tT1.start();// tT2.start(); TicketRunnable tR=new TicketRunnable(); Thread tT1=new Thread(tR,"一号窗口"); Thread tT2=new Thread(tR,"二号窗口"); tT1.start(); tT2.start(); }}//class TicketThread extends Thread{// private int ticket=5;// public TicketThread(String name){// super(name);// }// @Override// public void run() {// while(true){// System.out.println(this.getName()+":"+(ticket--));// if(ticket<1){// break;// }// }// }//}class TicketRunnable implements Runnable{ private int ticket=5; @Override public void run() { while(true){ System.out.println(Thread.currentThread().getName()+":"+(ticket--)); if(ticket<1){ break; } } }}
线程生命周期
终止线程的三种方法
使用退出标志,使线程正常退出,也就是当run方法完成后线程终止,推荐使用
使用stop方法强行终止线程(不推荐,因为stop和suspend、resume一样,也可能发生不可预料的结果)
使用interrupt方法中断线程
线程同步
线程同步是为了防止多个线程访问一个数据对象时,对数据造成破坏
是为保证多线程安全访问竞争资源的一种手段
同步和锁
package com.hgaong.synchronizedTest;public class BankDemo { public static void main(String[] args) { Bank bank=new Bank(); BankThread p1=new BankThread(bank); BankThread p2=new BankThread(bank); p1.start();//柜台取钱 p2.start();//ATM取钱 }}class BankThread extends Thread{ private Bank bank=null; public BankThread(Bank bank){ this.bank=bank; } @Override public void run() { System.out.println("取钱:"+bank.getMoney(400)); }}class Bank{ private int money=500; //取钱的方法,返回取钱的数目 //同时最多只能有一个线程调用此同步方法 public synchronized int getMoney(int number){ if(number<0){ return -1; }else if(money<0){ return -2; }else if(number-money>0){ return -3; }else{ try { Thread.sleep(1000);//模拟取钱时间 } catch (InterruptedException e) { e.printStackTrace(); } money-=number; System.out.println("余额:"+money); } return number; }}
class Bank { private int money = 500; // 取钱的方法,返回取钱的数目 public int getMoney(int number) { //同步代码块 synchronized (this) { if (number < 0) { return -1; } else if (money < 0) { return -2; } else if (number - money > 0) { return -3; } else { try { Thread.sleep(1000);// 模拟取钱时间 } catch (InterruptedException e) { e.printStackTrace(); } money -= number; System.out.println("余额:" + money); } return number; } }}
死锁:避免嵌套同步块
线程通信
生产者消费者问题
package com.hgaong.synchronizedTest;import java.util.LinkedList;public class ProductorConsumerDemo { public static void main(String[] args) { Backet backet=new Backet(); Productor productor=new Productor(backet); Consumer consumer=new Consumer(backet); productor.start(); consumer.start(); }}//生产者class Productor extends Thread{ private Backet backet=null; public Productor(Backet backet) { super(); this.backet = backet; } @Override public void run() { backet.pushApple(); }}//消费者class Consumer extends Thread{ private Backet backet=null; public Consumer(Backet backet) { super(); this.backet = backet; } @Override public void run() { backet.popApple(); }}class Backet{ private LinkedList<Apple> backet=new LinkedList<>(); //放4轮苹果 public synchronized void pushApple(){ for(int i=0;i<20;i++){ Apple apple=new Apple(i); push(apple); } } //取4轮苹果 public synchronized void popApple(){ for(int i=0;i<20;i++){ pop(); } } //向篮子放苹果 private void push(Apple apple){ //当篮子当中存放了5个苹果就等待并通知消费者来消费 if(backet.size()==5){ try { wait();//等待并释放当前对象的锁 } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } backet.addFirst(apple); System.out.println("存放:"+apple.toString()); notify();//通知消费者来消费 } //向篮子取苹果 private void pop(){ //当篮子当中苹果数为0时等待并通知生产者来生产 if(backet.size()==0){ try { wait();//等待并释放当前对象的锁 } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } Apple apple=backet.removeFirst(); System.out.println("吃掉:"+apple.toString()); notify();//通知生产者来生产 }}//苹果类class Apple { private int id; public Apple(int id) { this.id = id; } @Override public String toString() { return "苹果:" + (id + 1); }}
以上代码输出结果:
存放:苹果:1
存放:苹果:2
存放:苹果:3
存放:苹果:4
存放:苹果:5
吃掉:苹果:5
吃掉:苹果:4
吃掉:苹果:3
吃掉:苹果:2
吃掉:苹果:1
存放:苹果:6
存放:苹果:7
存放:苹果:8
存放:苹果:9
存放:苹果:10
吃掉:苹果:10
吃掉:苹果:9
吃掉:苹果:8
吃掉:苹果:7
吃掉:苹果:6
存放:苹果:11
存放:苹果:12
存放:苹果:13
存放:苹果:14
存放:苹果:15
吃掉:苹果:15
吃掉:苹果:14
吃掉:苹果:13
吃掉:苹果:12
吃掉:苹果:11
存放:苹果:16
存放:苹果:17
存放:苹果:18
存放:苹果:19
存放:苹果:20
吃掉:苹果:20
吃掉:苹果:19
吃掉:苹果:18
吃掉:苹果:17
吃掉:苹果:16
补充案例-单例模式
package com.hgaong.synchronizedTest;public class SingleTonDemo { public static void main(String[] args) { SThread sThread = new SThread(); Thread t1 = new Thread(sThread); Thread t2 = new Thread(sThread); t1.start(); t2.start(); }}class SThread implements Runnable { @Override public void run() { SingleTon.getInstance(); }}class SingleTon { private static SingleTon singleTon = null; private SingleTon() { System.out.println("单例模式"); } public static SingleTon getInstance() { if (singleTon == null) {//第一重检查 synchronized (SingleTon.class) { if (singleTon == null) {//第二重检查 singleTon = new SingleTon(); } } } return singleTon; }}
- java多线程学习总结
- java多线程学习总结
- Java多线程学习总结
- java多线程学习总结
- java 多线程学习总结
- java多线程学习总结
- Java学习总结--多线程
- java多线程学习总结
- java多线程-学习总结
- Java多线程学习总结
- Java多线程学习总结
- java多线程学习总结
- java多线程学习总结
- Java多线程-学习总结
- java学习--java多线程总结
- java学习之--多线程总结
- java多线程学习与总结
- 【Java多线程】的学习总结
- 《高效能人士的7个习惯》笔记
- Jquery实现点击切换单元格改变背景色
- SpringMVC从Controller跳转到另一个Controller
- 经典计算机图书-图解系列
- Openjudge 2.1 1813:熄灯问题
- java多线程-学习总结
- 多维尺度变换(multidimensional scaling, MDS)
- 机器学习(Machine Learning)&深度学习(Deep Learning)资料(Chapter 1)
- Linux下安装Joomla注意事项
- 实例1-2-输入两个数,输出较大者。
- 0416
- 如何快速转载CSDN中的博客
- JAVA保存文件
- 面向对象原则:高内聚、低耦合。