总觉的自己还有好多的东西还不懂,便很急促的学这学那没有方向,殊不知实质浪费了多少时间。
今天学习了多线程,来总结一下
多线程基础
先聊一下什么叫做进程。
在操作系统中,同时有许多个进程在运行,他们依照优先级排列,依次占用资源来运行。一个进程由多个线程组成。
Java在运行的时启动JVM,每个JVM相当于是一个进程,而其中至少会有俩个线程启动,分别是GC(垃圾回收机制),主线程(main)
多线程的俩种实现方法
1.继承Thread类,重写run()方法,利用该类中的start()方法来启动线程
class MyThread extends Thread{ //本质上Thread类是Runnable的实现类 但是单继承扩展性不好
String name;
int tacket = 5;
public MyThread(String name) {
this.name = name;
}
public void run() { //创建线程需要对run方法进行重写
while(tacket!=0){
System.out.println(name+tacket--);
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
MyThread mt = new MyThread("线程A"); //参数为线程名
MyThread mt1 = new MyThread("线程B");
mt.start(); //调用start方法自动调用run方法
mt1.start();
}
}
2.实现Runnable接口,必须重写run()方法,在利用Thread类的构造函数传入实现接口的引用,最后调用属于Thread类的start()方法启动
class Mythread1 implements Runnable{
int tacket = 5;
static String str ="";
public void run() {
// TODO Auto-generated method stub
while(tacket!=0){
str += Thread.currentThread().getName()+tacket--+"
";
}
}
}
public class RunnableDemo {
public static void main(String[] args) {
Mythread1 mt = new Mythread1();
Thread t = new Thread(mt,"线程A");
Thread t1 = new Thread(mt,"线程B");
Thread t3 = new Thread(mt);
t.start(); //调用start方法 CPU对线程进行调度 然后执run方法运行
t1.start();
}
}
俩种方法的比较
目前开发一般会使用第二种,也就是实现Runnable接口主要是有俩个原因
1.继承Thread是单继承,而实现Runnable接口提高了程序的可扩展性
2.实现Runnable接口可以资源实现共享
线程的状态:创建,就绪,运行,阻塞,终止
介绍一些线程的常用操作
static Thread currentThread()返回对当前正在执行的线程对象的引用。
String getName() 返回该线程的名称。
int getPriority()
返回线程的优先级。
主线程的优先级为5,最高优先级为10,最低优先级为1。
boolean isAlive()
测试线程是否处于活动状态。
static void sleep(long millis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
static void yield()
暂停当前正在执行的线程对象,并执行其他线程。
同步和死锁
资源共享时候使用同步(Synchronization),有俩种同步方法:
1.同步代码块 2.同步方法
同步代码块的效率要高于同步方法
同步方法直接在方法上加synchronized实现加锁,同步代码块则在方法内部加锁。
很明显,同步方法锁的范围比较大,而同步代码块范围要小点,一般同步的范围越大,性能就越差,一般需要加锁进行同步的时候,肯定是范围越小越好,这样性能更好。
在程序中过多的同步会发生死锁现象,及俩个线程一直处于相互等待状态,如果没有外力干扰会一直等待下去