线程的概述
进程: 计算机中特定功能的程序在数据集上的一次运行
线程: 计算机进程的一个单元
多线程: 一个进程有多个线程在同时运行
jvm: jvm是多线程的,在我们运行jvm的时候后台会运行垃圾回收的线程,来清理没有被引用的对象
进程与线程的区别:
进程之间互相隔离,不共享数据
同一个进程的线程之间可以共享数据
线程的实现
创建新执行线程有两种方法
一种方法是将类声明为Thread的子类.该子类应重写Thread类的run方法.接下来可以分配并启动该子类的实例.
线程启动的时候使用线程的start方法而不是run
继承Thread类
1.子类重写父类中的run方法,将线程运行的代码存放在run中,即:线程体
2.建立子类对象的同时线程也被创建
3.通过调用start方法开启线程
class MyThread extends Thread{
public void run(){
// 业务逻辑 , 线程体
}
}
public class ThreadDemo{
public static void main(String[] args){
new MyThread().start();
new MyThread().start();
}
}
另一种方法是声明实现Runnable接口的类.该类然后实现run方法,然后可以分配该类的实例,在创建Thread时作为一个参数来传递并启动.
实现 Runnable 接口
-
自定义类实现接口中的 run 方法。
-
通过 Thread 类创建线程,并将实现了 Runnable 接口的子类对象作为参数传递给 Thread 类的构造方法
3.Thread 类对象调用 start 方法开启线程
class MyThread implements Runnable{
public void run(){
// 业务逻辑 , 线程体
}
}
pulbic class ThreadDemo{
public static void main(String[] args){
MyThread t1 = new MyThread();
new Thread(t1).start();
new Thread(t1).start();
}
}
线程基本常用操作
获取线程名字: getName()
获取main方法所在线程名字:Thread.currentThread().getName()
设置线程名字: 对象.setname()
设置优先级: 对象.setPriority()
线程的加入: 对象.join() //执行完之后,再执行其他进程
线程的谦让: Thread.yield()
线程的控制: 对象.setDaemon(boolean on)
线程的终止: 对象.stop() //已过时
对象.interrupt() //推荐使用
线程执行原理
线程的并发执行是通过多个线程不断的切换CPU的资源,这个速度是非常快的,我们感觉不到,我们能感知到的是多个线程在并发的执行.
线程的生命周期
新建: 线程被 new出来
准备就绪: 线程具有执行的资格,即线程调用了 start(),没有执行的权利
运行: 具备执行的资格和具备执行的权利
阻塞: 没有执行的资格和执行权利
销毁: 线程的对象变成了垃圾,释放资源
并发
互联网的项目中存在着大量的并发的案例,如卖火车票,电商网站.
范例:火车找有100张票,4个窗口同时买票
分析: 4个窗口是4个线程同时在运行,100张票是4个线程的共享资源
采用继承Thread来实现,针对线程的安全问题,我们需要使用同步(就是要加锁,共享资源智能一个人同时访问)锁.
语法:
synchronized(锁对象){
//操作共享资源的代码
}
同步代码加在什么地方?
1.代码被多个线程访问
2.代码中有共享的数据
3.共享数据被多条语句操作
package com.czz.test01;
public class SaleTicket extends Thread{
private String name ;
public SaleTicket(String name ) {
super ( name );
}
// 加上 static, 表明 100 张票是共享的数据
private static int tickets = 100;
// 同步锁对象
private static Object obj = new Object ();
@Override
public void run() {
while ( true ) {
// 同步代码块
synchronized ( obj ) {
if ( tickets > 0) {
System. out .println( this .getName() + " 正在卖第 " + tickets -- + " 张票 " );
} else {
System. out .println( " 票已售罄 " );
break ;
}
}
}
}
}
测试对象
package com.czz.test01;
public class TicketTest {
public static void main(String[] args ) {
SaleTicket st1 = new SaleTicket( " 窗口 1" );
SaleTicket st2 = new SaleTicket( " 窗口 2" );
SaleTicket st3 = new SaleTicket( " 窗口 3" );
SaleTicket st4 = new SaleTicket( " 窗口 4" );
st1 .start();
st2 .start();
st3 .start();
st4 .start();
}
}