多线程与多进程
多线程的创建
常用方法
void start():启动线程,执行run()run():线程启动后执行String getName():返回线程名称void setName(String name):设置该线程名称static Thread currentThread():返回当前线程。在Thread子类中就是this,通常用于主线程和Runnable实现类static void yield():线程让步。其实就是线程异步join():线程并发堵塞static void sleep(long millis):指定单位为ms,让线程在指定时间内交出CPU控制权,时间到后才获得CPU控制权。 类似于python中的awaitstop():不保留任何未处理数据的强制关停线程boolean isAlive():bool判断线程是否存活
方式一:继承于Thread类
创建一个继承于Thread类的子类重写Thread类的run()创建Thread类的子类的对象通过此对象调用start()
class MyThread extends Thread{
@Override
public void run(){
System
.out
.println("多线程run成功");
}
}
class TreadTest{
public static void main(String
[] args
){
MyThread t1
= new MyThread();
t1
.start();
}
}
方式二:实现Runnable接口
定义子类,实现Runnable接口。子类中重写Runnable接口中的run方法。通过Thread类含参构造器创建线程对象。将Runnable接口的子类对象作为实际参数传递给Thread类的构造器中。调用Thread类的start方法:开启线程,调用Runnable子类接口的run方法。
区别
继承Thread实现Runnable
线程代码存放Thread子类run方法中线程代码存在接口的子类的run方法
实现方式的好处
避免了单继承的局限性多个线程可以共享同一个接口实现类的对象,非常适合多个相同线 程来处理同一份资源。
线程优先级
调度策略
时间片:“拉链图式”抢占式:优先级高的线程,优先获得cpu的控制权
Java的调度方法
同优先级默认组成队列,使用时间片策略对高优先级,优先使用抢占式
优先级等级
MAX_PRIORITY
:10
MIN _PRIORITY
:1
NORM_PRIORITY
:5
涉及的方法
getPriority():返回线程优先值setPriority(int newPriority):改变线程的优先级
补充
线程创建时继承父线程的优先级
低优先级只是获得调度的概率低,并非一定是在高优先级线程之后才被调用
Java中的线程分为两类:一种是守护线程,一种是用户线程
守护线程是用来服务用户线程的,通过在start()方法前调用 thread.setDaemon(true)可以把一个用户线程变成一个守护线程。
两者的唯一的区别是判断JVM何时离开
线程的生命周期
新建-就绪-运行->堵塞?->死亡并回收
线程同步 join
对于一些异步操作可能会脏库的操作,进行同步并发
多个线程执行的不确定性引起执行结果的不稳定
多个线程对账本的共享,会造成操作的不完整性,会破坏数据。
防止新线程溢出
class TicketDemo{
public static void main(String
[] args
){
Ticket t
= new Ticket();
Thread t1
= new Thread(t
);
Thread t2
= new Thread(t
);
Thread t3
= new Thread(t
);
t1
.setName("t1窗口");
t2
.setName("t2窗口");
t3
.setName("t3窗口");
t1
.start();
t2
.start();
t3
.start();
}
}
Synchronized的使用方法
方式一
synchronized(对象
){
}
方式二
public synchronized void show
(String name
){
}
注意:
必须确保使用同一个资源的多个线程共用一把锁,这个非常重要,否则就 无法保证共享资源的安全
一个线程类中的所有静态方法共用同一把锁(类名.class),所有非静态方 法共用同一把锁(this),同步代码块(指定需谨慎)
锁
死锁 DeadLock.java
不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃 自己需要的同步资源,就形成了线程的死锁出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于 阻塞状态,无法继续
解决方法
专门的算法、原则尽量减少同步资源的定义尽量避免嵌套同步
public class DeadLockTest {
public static void main(String
[] args
) {
final StringBuffer s1
= new StringBuffer();
final StringBuffer s2
= new StringBuffer();
new Thread() {
public void run() {
synchronized (s1
) {
s2
.append("A");
synchronized (s2
) {
s2
.append("B");
System
.out
.print(s1
);
System
.out
.print(s2
);
}
}
}
}.start();
new Thread() {
public void run() {
synchronized (s2
) {
s2
.append("C");
synchronized (s1
) {
s1
.append("D");
System
.out
.print(s2
);
System
.out
.print(s1
);
}
}
}
}.start();
}
}
锁的释放
当前线程的同步方法、同步代码块执行结束当前线程在同步代码块、同步方法中遇到break、return终止了该代码块、 该方法的继续执行当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导 致异常结束当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线 程暂停,并释放锁
不释放的锁
线程执行同步代码块或同步方法时,程序调用Thread.sleep()、 Thread.yield()方法暂停当前线程的执行线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程 挂起,该线程不会释放锁(同步监视器)应尽量避免使用suspend()和resume()来控制线程
单例设计模式之懒汉式(线程安全)
class Singleton {
private static Singleton instance
= null
;
private Singleton(){}
public static Singleton
getInstance(){
if(instance
==null
){
synchronized(Singleton
.class){
if(instance
== null
)
{
instance
=new Singleton();
}
}
}
return instance
;
}
}
public class SingletonTest{
public static void main(String
[] args
){
Singleton s1
=Singleton
.getInstance();
Singleton s2
=Singleton
.getInstance();
System
.out
.println(s1
==s2
);
}
}