黑马程序员——多线程
来源:互联网 发布:打鼓谱软件 编辑:程序博客网 时间:2024/06/05 05:27
------- android培训、java培训、期待与您交流! ----------
要了解线程,就要了解进程,线程和程序之间相互关系。
1. 进程是程序的一次执行过程,从源代码加载,执行,直至完成一个完整过程。
2. 线程是控制流,也是一个执行过程,但执行单位比进程小。
线程与进程比较:
共同点:
都是一个程序的执行过程。
不同点:
进程是一个实体,每个进程有自己的状态,专用数据段(独立内存资源);同一个进程下的线程则共享进程的数据段。
3. 线程的生命周期
一个线程的创建,工作,死亡的过程称为线程的生命周期。
线程生命周期公有5个阶段:新建状态,就绪状态,运行状态,阻塞状态和死亡状态。
①. 新建状态:新建状态是指创建一个线程,但它还没启动。处于新建状态的线程对象,只能够被启动或终止。Example:以下代码使线程myThread处于新建状态:
Thread myThread= new Thread();
②. 就绪状态:就绪状态是当线程处于新建状态后,调用了start()方法,线程就处于就绪状态。
就绪状态具备运行条件,但尚未进入运行状态。处于就绪状态的线程可有多个,这些线程将在就绪队列中排队,等待cpu资源。
Example:以下代码使线程myThread进入就绪状态:
myThread.start();
③.运行状态:
运行状态就是某个就绪状态的线程获得了cpu资源,正在运行。
④ .阻塞状态:
阻塞状态就是正在运行的线程遇到某个特殊情况:例如:延迟,挂起,等待I/O操作完成等。
⑤.死亡状态
线程不具有继续运行的能力,也不能转到其他的状态。
4. 线程调度与优先级
线程调度采用抢占式,优先级高的比优先级低的优先运行。
优先级相同的情况下,按先来先服务的原则运行。
5. java实现多线程应用有两种途径。
①.继承Thread类,申明Thread子类,用Thread子类创建线程对象。
②.在类中实现Runnable接口,在类中提供Runnable接口的run()方法。
6. Thread类
①.定义继承Thread方法。
②.复写Thread类中的run方法。目的是将自定义的方法存储在run方法中,让线程运行。
③.调用start方法,该方法有两个作用:启动线程,jvm调用run方法。
例如程序:
class Demo extends Thread
{
private Stringname;
Demo(String name)
{
this.name=name;
}
public void run()
{
for(int i=0;i<10;i++)
{
System.out.println(this.getName()+"\tgood luckto myself"+i);
}
}
}
public class univer
{
public static void main(String[] args)
{
Demo t1 = new Demo("one+");
Demo t2 = new Demo("two+");
t1.start();
t2.start();
for(int j=0;j<10;j++)
{
System.out.println("main......"+j);
}
}
}
程序分析:
Demo类继承Thread类,复写run方法。
New Demo()建立线程。t1.start();t2.start();开启线程,使线程处于就绪状态。由jvm觉得运行谁。
getName()是获取线程的名字。从这个方法可以看出,线程有默认的名字。
例如:Thread-1 good luckto myself7
Thread-1 good luckto myself8
Thread-1 good luckto myself9
Thread-0 good luckto myself9
线程默认名为:类名—编号。编号从0开始。
另外:注意Thread类的另一个方法:static Thread currentThread()方法,返回当前正在执行线程一个引用:故this ==Thread.currentThread()即有:Thread.currentThread().getName();相当于this.getname();
7. 实现接口Runnable:
Java.lang.Runnable接口,只有run方法需要实现,一个实现Runnable接口的类实际上定义了一个在主线程之外的新线程的操作。
①. 定义类实现Runnable接口
②. 覆盖Runnable接口中的Run方法。将要运行的代码放在该run方法中。
③. 通过Thread类建立线程对象。
④. 将Runnable子类对象作为实际参数传递给Thread类的构造函数。
为什么要将Runnable接口子类对象作为参数传递给Thread类的构造函数?
因为:自定义run方法所属的对象是Runnable子类对象。
所以要让线程去指定对象的run方法。就必须明确该run方法所属的对象。
⑤. 调用Thread类的start方法开启线程。并由jvm调用Runnable子类的run方法。
⑥. 实现方式和继承方式的区别?
实现方式的好处:避免了单继承的局限性,在定义线程时,建议使用实现方式。
Example:
class Demo implements Runnable
{
private Stringname;
Demo(String name)
{
this.name=name;
}
public void run()
{
for(int i=0;i<10;i++)
{
System.out.println(name+"\tgood luckto myself"+i);
}
}
}
public class univer
{
public static void main(String[] args)
{
Demo d1 = new Demo("one");
Demo d2 = new Demo("two");
Thread t = new Thread(d1);
Thread t1 = new Thread(d2);
t.start();
t1.start();
for(int j=0;j<10;j++)
{
System.out.println("main......"+j);
}
}
}
程序实现了Runnable接口,创建了两个线程,加上主线程,给程序一共三个线程。
7.线程的同步于互斥
通常情况下,程序中多个线程是相互协调和相互联系的,多线程之间存在着互斥与同步。
发生同步的原因:
当多条语句操作同一个线程的共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行,导致了共享数据的错误。
class Ticket implements Runnable
{
private int tick=10;
public void run()
{
while(true)
{
if(tick>0)
{
for(int i=0;i<10;i++)
{
System.out.println("\tgood luckto myself"+tick--);
}
}
}
}
}
public class univer
{
public static void main(String[] args)
{
Ticket i = new Ticket();
Thread t = new Thread(i);
Thread t1 = new Thread(i);
t.start();
t1.start();
for(int j=0;j<10;j++)
{
System.out.println("main......"+j);
}
}
}
程序分析:改程序有两个线程:t和t1,开启线程后,t和t1共享数据tick,t进入到if(tick>0)后,t1由于tick还是大于0,满足条件。故t,t1都进入if语句内部。
当tick=1时,t和t1给tick减了两次,故造成了tick数据的错误:
解决办法:
对多条操作共享数据,每次只允许一个线程对其进行操作,其他线程不能进入:
专业解决方式:同步代码块:
Synchronized(对象)
{
需要被同步代码;
}
参数对象如同锁,持有锁的线程可以在同步中运行。没有持有锁的线程即使获取了cpu的执行权也进不去。
好处:解决多线程的安全问题。
弊端:多个线程需要判断锁,较消耗资源。
Example:
class Ticket implements Runnable
{
private int tick=10;
Object obj = new Object();
public void run()
{
while(true)
{
synchronized(obj)
{
if(tick>0)
{
for(int i=0;i<10;i++)
{
System.out.println("\tgood luckto myself"+tick--);
}
}
}
}
}
}
public class univer
{
public static void main(String[] args)
{
Ticket i = new Ticket();
Thread t = new Thread(i);
Thread t1 = new Thread(i);
t.start();
t1.start();
for(int j=0;j<10;j++)
{
System.out.println("main......"+j);
}
}
}
注意:synchronized(对象)括号里面的对象只是一个对象,这个对象可以是任何类自定义类的对象,对象与程序没有太大关系。对象只是提供了一个锁的机制。
------- android培训、java培训、期待与您交流! ----------
详情请查看:
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- win7通过SecureCRT链接ubuntu方法总结
- 原型模式
- 用POST方式 重定向
- FileInputStream/FileOutputStream的应用
- 1044: 任意进制转换
- 黑马程序员——多线程
- Redirect in response to POST transaction
- 读《精通CSS》第三版 ——对链接应用样式
- 如何成为一个技术“牛人”
- 307 - Sticks
- 通过sql语句查询表的列和对应的数据并在jsp页面上显示
- 关于STM32的systick定时器的详细说明
- Python Post 请求
- ssh 后台执行java 程序