线程的概述
进程: 计算机中特定功能的程序在数据集上的一次运行
线程: 计算机进程的一个单元
多线程: 一个进程有多个线程在同时运行
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
接口
1.
自定义类实现接口中的
run
方法。
2.
通过
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();
}
}