动态的概念。
线程是进程中的一条完整的执行的路径。线程是进程中的一个任务线。
线程的特点:
1:线程不能独立存在,必须在某一个进程中存活。
2:多个线程可以并发执行。
3:进程提供了一个线程生存的环境,进程中所有的任务(代码)都是依靠进程中的线程来完成的。
4:一个进程中至少要有一个线程。当然可以有多个线程。
5:当一个进程启动的时候,会先启动一个线程。这个线程称为主线程。
6:线程是cpu进行调度执行的最小单位。
7:一个进程中的多个线程共享所在的进程的资源。
举个栗子:
1:迅雷 :进程。迅雷中的每一个下载的任务线可以看作一个线程。
2:进程:高速公路。线程:车道。
进程和线程的关系:
1:进程可以独立存在,是cpu 进行资源分配的最小单位。
2:线程是依赖于某一个进程的。是cpu进行调度执行的最小单位。
3:一个进程中至少有一个线程。如果一个进程中所有的线程都over了。进程也 over。
4:可以把线程看作轻量级的进程。启动进程和销毁进程是比较消耗系统资源的。在进程中启动和销毁一个线程消耗的系统资源要少。
5:进程和线程都是可以并发执行的。
单线程程序的问题:
1:一旦代码中存在阻塞的方法,那么整个进程都将进入等待的状态。等待将产生阻塞的原因消除掉,才能继续执行。
多线程程序:
1:某一个线程被阻塞了,其他的线程不受任何的影响。
列:qq登录:
1:一个独立的线程来绘制登录的动画效果。
2:一个独立的线程来监听服务器的反馈的信息。一旦信息回来,立马处理。
线程的实现:
java 的jdk 中 定义了一个描述线程的类-->java.lang.Thread.
任何的一个线程的执行的主体,都对应这一段代码任务。
java 线程的实现:
首先在main 线程中去创建启动我们自定义的线程。
1:继承线程类。
2:实现java.lang.Runnable。
3: 实现一个Callable 接口。 jdk1.5 出现的。
利用线程实现来模拟火车票购票系统:
package com.bjsxt.thread0917;
/**
* 继承线程类的方式去 模拟火车站卖票
* @author yhl
*
*/
public class ThreadTicketTest {
public static void main(String[] args) {
//创建唯一的票务系统对象
Ticket ticket = new Ticket();
//创建售票员对象
TicketSaler saler1 = new TicketSaler(ticket);
//设置线程的名字
saler1.setName("售票员-1");
TicketSaler saler2 = new TicketSaler(ticket);
saler2.setName("售票员-2");
TicketSaler saler3 = new TicketSaler(ticket);
saler3.setName("售票员-3");
TicketSaler saler4 = new TicketSaler(ticket);
saler4.setName("售票员-4");
TicketSaler saler5 = new TicketSaler(ticket);
saler5.setName("售票员-5");
//启动线程执行 jvm 会调用执行 run 方法。 不要自己去调用 run 方法。
saler1.start();
saler2.start();
saler3.start();
saler4.start();
saler5.start();
}
}
//票务系统的类 可以使用单例模式
class Ticket{
//余票
private int count = 100;
/**
* 卖票的行为
* @param count 本次出售几张票
* @return 如果出票成功,返回true ,否则 返回 false。
*/
public boolean sale(int count){
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
if(this.count >= count){
this.count -= count;
System.out.println(Thread.currentThread().getName() + "\t卖出了 "+ count +" 张票!余票为:"+this.count);
return true;
}
System.out.println(Thread.currentThread().getName() + " 出票失败!余票不足! " + "余票为:"+ this.count);
return false;
}
}
//使用继承线程类的方式 创建线程,模拟售票员 阿姨
class TicketSaler extends Thread{
//持有被访问的票务系统的引用。
private Ticket ticket;
public TicketSaler(Ticket ticket) {
super();
this.ticket = ticket;
}
//这样写,每创建一个售票员线程,就会创建一个独立的票务系统。
// Ticket ticket = new Ticket();
//run 方法就是当前线程 的任务的执行的主体
public void run() {
boolean result = ticket.sale(1);
while(result){
result = ticket.sale(1);
}
}
}
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
package com.bjsxt.thread0917;
/**
* 实现 java.lang.Runnable 接口。
* @author yhl
*
*/
public class RunnableThreadTest {
public static void main(String[] args) {
TicketRunnable runnable = new TicketRunnable();
//创建了5个线程对象,执行同一个runnable 的run 方法。访问同一个票务系统。
Thread sale1 = new Thread(runnable);
sale1.setName("售票员-1");
Thread sale2 = new Thread(runnable);
sale2.setName("售票员-2");
Thread sale3 = new Thread(runnable);
sale3.setName("售票员-3");
Thread sale4 = new Thread(runnable);
sale4.setName("售票员-4");
Thread sale5 = new Thread(runnable);
sale5.setName("售票员-5");
//调用 Thread 类的run 方法。 run 方法中会 调用 执行 runnable 实例的 run 方法。
sale1.start();
sale2.start();
sale3.start();
sale4.start();
sale5.start();
}
}
class TicketRunnable implements Runnable{
//票务系统
private Ticket ticket = new Ticket();
//线程的主体代码
public void run() {
boolean result = ticket.sale(1);
while(result){
result = ticket.sale(1);
}
}
}
1:继承线程类:
优点:容易理解。代码实现简单。
缺点:不能继承其他的类。多个线程对象共享同一个数据,处理稍微复杂(持有同一个对象的引用、单例(局限性))。
2:实现java.lang.Runnable 接口
优点:可以再继承其他的类。多个线程对象共享同一个数据处理比较容易。直接在 Runnable 的子类中 创建该实例对象即可。
缺点:理解稍微复杂(代理设计模式)。代码实现稍微的复杂。
了解:
操作系统具有创建进程,和进程中线程的权利。
jvm,程序是没有权限去创建进程和线程的。
java 中线程的创建,是向jvm申请,jvm 再向系统申请。