Java学习day06--线程-同步-线程状态
线程-同步-线程状态
该部分主要讲解java线程的创建方式、线程的常用成员方法、多线程安全问题解决方法以及线程状态。
java线程的创建方式
- 自定义类继承自Thread,并且重写run():
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("i = " + i);
}
}
}
之后在测试类中调用start()方法启动线程。
- 自定义类实现Runnable接口,并重写run()方法。之后传入Thread(Runnable target)构造方法即可。
// 实现接口类
public class RunAbleClass implements Runnable{
int index = 0;
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println("我是小可爱" + index++);
}
}
}
// 测试类
public class Demo {
public static void main(String[] args) throws InterruptedException{
RunAbleClass rc = new RunAbleClass();
Thread t = new Thread(rc);
t.start();
}
}
两种创建方式的区别:
1).第一种方式:需要子类“继承自Thread”–Java是单继承,对子类有限制。
2).第二种方式:需要子类“实现Runnable接口”–Java可以同时实现多个接口,对子类比较宽松。【建议】
多线程构造方法
1).public Thread()
:分配一个新的线程对象。
2).public Thread(String name)
:使用线程名称构造一个Thread。可以通过getName()获取线程名;
注意:每个线程默认会有一个线程名称:Thread-[索引值]
线程名称的作用:区分每个线程。
3).public Thread(Runnable target)
:分配一个带有指定目标新的线程对象。
Thread类常用成员方法
1)public String getName()
:获取线程名称;设置线程名称可以通过“构造方法”设置。
2) public void setName(String name)
:也可以设置线程名称。
3)public static void sleep(long m)
:让当前线程休眠指定的毫秒。
4)public static Thread currentThread()
:获取当前的线程对象;
匿名内部类的方式实现线程
方式一:
new Thread(){public void run(){
System.out.println("匿名内部类实现");
}
}.start();
方式二:
new Thread(new Runnable(){
public void run(){
System.out.println("Runnable子类的run...");
}
}).start();
三种方式解决多线程安全问题
- 同步代码块
方法(){
synchronized(锁对象){
//需要同步的代码
}
}
锁对象:可以是“任何对象”,有两个要求:
1).必须是引用类型的对象;
2).多个线程必须共享同一个锁对象;
- 同步方法:
public synchronized int getTicket(){
//正常写代码即可
}
其它说明:
1."静态方法"可以被声明为“同步方法”:
//锁对象:本类的Class对象
public static synchronized void show(){
}
2)."静态方法"方法可以包含“同步代码块”:
public static void show(){
synchronized(本类的class对象/静态对象){
}
}
- Lock锁
JDK5以后提供了比synchronized更灵活的锁:Lock
public class Tickets implements Runnable {
public int tickets = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
lock.lock();//加锁
try {
if (tickets > 0) {
int n = tickets;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
tickets--;
System.out.println(Thread.currentThread().getName() +
" 取走一张票:" + n);
} else {
System.out.println("没票了!");
break;
}
}finally {
lock.unlock();//解锁
}
}
}
}
线程状态
- NEW(新建) 线程刚被创建,但是并未启动。还没调用start方法。
- Runnable(可运行)
线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操
作系统处理器。 - Blocked(锁阻塞)
当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状
态;当该线程持有锁时,该线程将变成Runnable状态。 - Waiting(无限等待)
一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个
状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。 - TimedWaiting(计时等待)
同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态
将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、
Object.wait。 - Teminated(被终止)
因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。