Thread(26)
1、进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。
2、线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。
简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。
3、多线程:具有多个执行代码路径。
4、Thread类是一个标准的线程对象。两个路径,两个线程,在抢夺CPU资源(时间)。
5、创建线程步骤:
1、定义一个类继承Thread。
2、重写 run 方法。
3、创建子类对象,就是创建线程对象。
4、使用start方法,开启线程并让线程执行,同时还会告诉JVM去调用run方法。
6、定义类实现Runnable接口:
public class Demo02 {
public static void main(String[] args) {
//创建线程执行目标类对象
Runnable runn = new MyRunnable();
//将Runnable接口的子类对象作为参数传递给Thread类的构造函数
Thread thread = new Thread(runn);
Thread thread2 = new Thread(runn);
//开启线程
thread.start();
thread2.start();
for (int i = 0; i < 10; i++) {
System.out.println("main线程:正在执行!"+i);
}
}
}
class MyThread extends Thread { //继承Thread
MyThread(String name){
super(name);
}
//复写其中的run方法
public void run(){
for (int i=1;i<=20 ;i++ ){
System.out.println(Thread.currentThread().getName()+",i="+i);
}
}
}
class ThreadDemo {
public static void main(String[] args) {
//创建两个线程任务
MyThread d = new MyThread();
MyThread d2 = new MyThread();
d.run();//没有开启新线程, 在主线程调用run方法
d2.start();//开启一个新线程,新线程调用run方法
}
}
7、 自定义线程执行任务类:
public class MyRunnable implements Runnable{ //定义线程要执行的run方法逻辑
@Override
public void run() { for (int i = 0; i < 10; i++) {
System.out.println("我的线程:正在执行!"+i);
}
}
}
8、为什么需要定一个类去实现Runnable接口呢?继承Thread类和实现Runnable接口有啥区别呢?
实现Runnable接口,避免了继承Thread类的单继承局限性。覆盖Runnable接口中的run方法,将线程任务代码定义到run方法中。
创建Thread类的对象,只有创建Thread类的对象才可以创建线程。线程任务已被封装到Runnable接口的run方法中,而这个run方法所属于Runnable接口的子类对象,所以将这个子类对象作为参数传递给Thread的构造函数,这样,线程对象创建时就可以明确要运行的线程的任务。
9、线程的匿名内部类使用。
方式1:创建线程对象时,直接重写Thread类中的run方法。
new Thread() {
public void run() {
for (int x = 0; x < 40; x++) {
System.out.println(Thread.currentThread().getName() + "...X...." + x);
}
}
}.start();
方式2:使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法。
Runnable r = new Runnable() {
public void run() {
for (int x = 0; x < 40; x++) {
System.out.println(Thread.currentThread().getName()
+ "...Y...." + x);
}
}
};
new Thread(r).start();
10、线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
作用:线程池主要用来解决线程生命周期开销问题和资源不足问题。通过对多个任务重复使用线程,线程创建的开销就被分摊到了多个任务上了,而且由于在请求到达时线程已经存在,所以消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使用应用程序响应更快。另外,通过适当的调整线程中的线程数目可以防止出现资源不足的情况。
11、 使用线程池中线程对象的步骤:
1、创建线程池对象。
2、 创建Runnable接口子类对象。
3、提交Runnable接口子类对象。
4、关闭线程池。
public class ThreadPoolDemo {
public static void main(String[] args) {
//创建线程池对象
ExecutorService service = Executors.newFixedThreadPool(2);//包含2个线程对象
//创建Runnable实例对象
MyRunnable r = new MyRunnable(); //自己创建线程对象的方式
//Thread t = new Thread(r);
//t.start(); ---> 调用MyRunnable中的run() //从线程池中获取线程对象,然后调用MyRunnable中的run()
service.submit(r);
//再获取个线程对象,调用MyRunnable中的run()
service.submit(r);
service.submit(r);
//注意:submit方法调用结束后,程序并不终止,是因为线程池控制了线程的关闭。将使用完的线程又归还到了线程池中 //关闭线程池
//service.shutdown();
}
} //Runnable接口实现类: public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("我要一个教练"); try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("教练来了: " +Thread.currentThread().getName());
System.out.println("教我游泳,交完后,教练回到了游泳池");
}
}
12、静态方法内不允许直接调非静态的方法。栈内存,都是线程私有的。
13、Thread.currentThread() 获取当前线程对象,也就是说运行在本类中run 方法所对应的线程对象。方法调用链:Thread.currentThread() .getName() 获取当前线程对象的名字。
14、Thread对象方法:sleep(毫秒参数a) /// 线程睡觉a毫秒自动醒来再接着执行代码。
15、第二种方式Runnable实现线程的好处:避免了单继承的局限性。更加的符合面向对象。较为常用。实现Runnable接口,将线程任务单独分离出来封装成对象,类型呢就是Runnable接口类型,Runnable接口对线程对象和线程任务进行解耦。还有另一个好处就是:让你的资源能够共享。
public class RunnableDemo implements Runnable{ public RunnableDemo() {
super();
} public void run(){
for(int i=0;i<1;i++){
try{
Thread.sleep(1000);
}catch(Exception ex){}
System.out.println("runnable"+i);
}
}
}
16、高内聚:自己的事情自己做,自己能做的事情绝不让外面的人去做。 低耦合:尽量降低类与类之间的联系性。而接口的应用就恰好帮你完成这件事。
17、线程的生命周期:new - runnable - blocked (受阻塞) - waiting - time waiting - terminated (结束)
18、线程生命周期图解:
19、线程池(缓冲池):
20、从JDK5以后,就内置了线程池技术,直接使用。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class ThreadPoll {
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit(new ThreadPollRunnable());
es.submit(new ThreadPollRunnable());
es.submit(new ThreadPollRunnable());
}
}
21、Runnable接口方法run有两个缺点:1、 无返回值 void。 2、 不能抛异常。 Callable接口就能解决这个问题。
22、父类有抛出异常,子类可抛可不抛出异常。
23、泛型不能写基本类型,要写基本类型的包装类,否则会报错误 “Syntax error, insert "Dimensions" to complete ReferenceType”。
24、双线程求和 Callable接口实现类泛型。
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; public class ThreadPoll {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService es = Executors.newFixedThreadPool(2);
Future<Integer> ft1 = es.submit(new CallableDemo(100));
Future<Integer> ft2 = es.submit(new CallableDemo(200));
System.out.println("sum1 "+ ft1.get());
System.out.println("sum2 "+ ft2.get());
es.shutdown();
}
}
import java.util.concurrent.Callable; public class CallableDemo implements Callable<Integer>{
private int a; public CallableDemo(int num){
a = num;
} public Integer call(){
int i = a;
int sum = 0;
while(i > 0){
sum = sum + i;
i--;
}
return sum;
}
}
25、多线程同时操作一个共享数据的时候,往往会出现线程安全问题。(多窗口卖票案例中,判断有票情况下,没减减就被别的线程抢去资源了(失去CPU时间),等获得CPU时间的时候,再执行往下的代码就会出现问题。)
26、同步代码块解决线程安全问题。 线程共享数据,保证安全,加入同步代码块 synchronized(任意对象){ 线程要操作的共享数据 } 同步代码块 =》 线程安全就意味着运行速度必然降低。牺牲速度来保证安全! 安全问题的前提条件是:多线程,操作共享数据。
27、同步保证安全性:同步锁(对象监视器)的原理:
28、同步方法: StringBuffer类(线程安全)的方法都是同步方法 synchronized. 而它兄弟 StringBuiilder是线程不安全的,类中方法没有同步方法。
public class Tickets implements Runnable {
private int ticket = 100; public void run (){
while(true){
saleTicket();
}
} public synchronized void saleTicket(){
if(ticket > 0){
try{
Thread.sleep(10);
}catch(Exception ex){}
System.out.println(Thread.currentThread().getName()+"售出第"+ ticket-- + "张票~");
}
}
}
29、静态优先于非静态的存在。静态方法内不能引用非静态的成员变量等。
30、静态方法的同步锁是:本类类名.class 非静态方法的同步锁就是 this
31、JDK1.5新特性 Lock 比 synchronized 更加地灵活, 获取锁和释放锁地操作都能看见。
32、线程的死锁原理:(两人抓头发,你等着我松手,我等着你松手)
代码实现:
public class DeadLock implements Runnable{
private int i = 0; public void run(){
while(true){
if(i % 2 == 0){
//先进入A同步,再进入B同步
synchronized(LockA.locka){
System.out.println("if...locka");
synchronized(LockB.lockb){
System.out.println("if...lockb");
}
}
}else{
//先进入B同步,再进入A同步
synchronized(LockB.lockb){
System.out.println("else...lockb");
synchronized(LockA.locka){
System.out.println("else...locka");
}
}
}
i++;
}
}
}
33、线程等待与唤醒案例安全解决:一切为了不出现人妖问题。 问题产生原因:赋值时被抢夺了CPU时间,导致后半部分的赋值未完成就被打印值。
解决方案1:synchronized(唯一的对象){ 共享数据代码块 }
解决方案2:使用线程间的通信方法 .wait() 与 .notify()
====》 .wait() 与 notify() 方法。
Thread(26)的更多相关文章
- [易学易懂系列|rustlang语言|零基础|快速入门|(26)|实战3:Http服务器(多线程版本)]
[易学易懂系列|rustlang语言|零基础|快速入门|(26)|实战3:Http服务器(多线程版本)] 项目实战 实战3:Http服务器 我们今天来进一步开发我们的Http服务器,用多线程实现. 我 ...
- MyBatis知多少(26)MyBatis和Hibernate区别
iBatis和Hibernate之间有着较大的差异,但两者解决方案很好,因为他们有特定的领域.我个人建议使用MyBatis的,如果: 你想创建自己的SQL,并愿意维持他们. 你的环境是由关系数据模型驱 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(26)-权限管理系统-分配角色给用户
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(26)-权限管理系统-分配角色给用户 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x ...
- Windows Phone开发(26):启动器与选择器之MediaPlayerLauncher和SearchTask
原文:Windows Phone开发(26):启动器与选择器之MediaPlayerLauncher和SearchTask 启动器与选择器简单的地方在于,它们的使用方法几乎一模一样,从前面几节中,我相 ...
- [.net 面向对象程序设计深入](26)实战设计模式——策略模式 Strategy (行为型)
[.net 面向对象程序设计深入](26)实战设计模式——策略模式 Strategy (行为型) 1,策略模式定义 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模 ...
- Thread(线程)和ThreadPool(线程池) Thread回调与返回值
Thread(线程) Thread开启线程:接收一个参数 TestClass tc = new TestClass(); //没有返回值,有一个object类型的参数的委托:两种写法. Paramet ...
- Qt 学习之路 2(26):反走样
Qt 学习之路 2(26):反走样 豆子 2012年11月12日 Qt 学习之路 2 9条评论 我们在光栅图形显示器上绘制非水平.非垂直的直线或多边形边界时,或多或少会呈现锯齿状外观.这是因为直线和多 ...
- Flutter学习笔记(26)--返回拦截WillPopScope,实现1秒内点击两次返回按钮退出程序
如需转载,请注明出处:Flutter学习笔记(26)--返回拦截WillPopScope,实现1秒内点击两次返回按钮退出程序 在实际开发中,为了防止用户误触返回按钮导致程序退出,通常会设置为在1秒内连 ...
- leecode刷题(26)-- 用栈实现队列
leecode刷题(26)-- 用栈实现队列 用栈实现队列 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- 返 ...
随机推荐
- 第一章:HTML5的基础
HTML5基础 1.DoctYpe声明 <!DCTYPE html>必须放在第一行. <title> <title> 百度</title> <me ...
- RN NetInfo使用
代码: class NetInfoView extends Component { getNetInfo() { //如果是andorid的程序,需要在xml添加获取网络请求权限 NetInfo.fe ...
- 小睿开始呼叫用户,然后FS怎么跟用户交互的整个流程原理
学习从小睿开始呼叫用户,然后FS怎么跟用户交互的整个流程原理; 1.小睿向欣方新发起呼叫请求; 2.欣方新可以通过线路发起SIP协议请求,来呼叫用户; 3.当用户接通后,将建立 ...
- react 脚手架--create-react-app
1.yarn add -g create-react-app 2.create-react-app demo cd demo yarn start 可以跑起来整个项目了 一般都会用到路由,需要 yar ...
- 两种ps切图方法(图层/切片)
两种Ps切图方法 一. 基础操作: a) Ctrl++ 放大图片,ctrl - -缩小图片 b) 按住空格键space+,点击鼠标左键,拖动图片. c) 修改单位,点击编辑 ...
- content_type
1.作用 将app名称与其中表关系进行保存 在models创建表时,关联到ContentType并不会产生实际的字段 2.使用 在models中代码 from django.db import mod ...
- [django]梳理drf知识点
要实现的功能 idc_list/ get 列出所有 post 创建一个idc idc_detail/1/ get 获取一个idc put 修改一个idc delete 删除一个idc 一般url是这样 ...
- 【EatBook】-NO.2.EatBook.2.JavaArchitecture.1.001-《修炼Java开发技术在架构中体验设计模式和算法之美》-
1.0.0 Summary Tittle:[EatBook]-NO.2.EatBook.2.JavaArchitecture.1.001-<修炼Java开发技术在架构中体验设计模式和算法之美&g ...
- elasticsearch6.0.0源码导入到idea总结
由于elasticsearch使用了gradle管理依赖,进行构建,再加上对gradle没有接触过. 因此,导入到idea中遇到问题非常多.这里大致罗列下并说明解决方法. 环境背景 gradle版本: ...
- git revert 撤销merge的动作
在执行完git merge提交以后,通常会merge过的分支的提交记录都带过来,比如A分支merge到了B分支,那么B分支上肯定有A分支的提交记录,如果此时要回退这个merge动作,是产生一条reve ...