---------------------android培训、java培训、java学习型技术博客、期待与您交流! -------------------
线程是程序执行的一条路径, 一个进程中可以包含多条线程
多线程并发执行可以提高程序的效率, 可以同时完成多项工作
jvm启动的时候会有一个进程java.exe
该进程中至少有一个线程负责java程序的执行,而且这个线程的代码存在于main方法中,该线程称之为主线程。
扩展知识:
其实更细节说虚拟机,jvm启动不止一个线程,还有一个负责垃圾回收机制的线程
创建新线程的方法:
方法一:
1.继承Thread,步骤如下:
a、定义类继承Thread
b、重写run()方法
c、把新线程要做的事写在run方法中
d、创建线程对象
e、开启新线程, 内部会自动执行run方法
代码如下:将类声明为Thread的子类
//1、定义类继承Thread类
class ThreadDemo extends Thread{
//2、重写run()方法
public void run(){
System.out.println("线程运行了");
}
}
class Demo{
public static void main(String[] args){
ThreadDemo td = new ThreadDemo();
//td.run();
//仅仅是对象调用方法,线程创建了,并没有执行,该方法被主函数所调用,只有执行完才会执行下面的代码。
td.start(); //开启了线程,并执行该线程的run()方法
}
}
2.实现Runnable接口的步骤:
a、定义类实现Runnable接口;
b、覆盖Runnable接口中的run()方法,将线程要运行的代码存放在run()方法中
c、通过Thread类建立线程对象;
d、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数;
为什么要将Runnable接口的子类对象传递给Thread类的构造函数?
因为,自定义的run()方法所属的对象是Runnable接口的子类对象,所以要让线程去执行指定对象的的run()方法,就必须明确该run()方法的对象。
e、调用Thread类的start()方法开启线程并调用Runnable接口子类的run()方法。
代码如下:
class ThreadDemo implements Runnable {
public void run(){
System.out.println("Runnable接口实现方式");
}
}
class Demo {
public static void main(String[] args){
//创建Runnable接口的子类对象
ThreadDemo td = new ThreadDemo();
//将Runnable接口的子类对象传给Thread类的构造函数
Thread t = new Thread(t);
t.start(); //启动线程
}
}
多现程的运行出现了安全问题
出现的原因:当多条语句,在操作同一共享数据时,一个线程对多条语句只执行一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。
解决办法:
对多条操作共享数据的语句,在某一时间段,只能让一个线程访问,java对于多线程的安全问题提供了专业的解决方式,就是同步代码块。
同步函数用的是哪一个锁呢?
函数需要被对象调用,那么函数都有一个所属对象引用,就是this,所以同步函数使用的锁是this
如果同步函数被静态static修饰,使用的锁是什么呢?
通过验证,发现不再是this。因为静态方法中也不可以定义this
静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件,即类名.class,访问对象的类型是class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象,也就是 类名.class (面试可能问到的问题)
class Single {
private static Single s = null; //创建类的引用,先不创建对象
private Single(){} //私有构造函数
public static Single getInstance(){ //提供公共的访问
if (s==null){ //判断引用是否为空
synchronized(Single.class){ //同步代码块,里面的对象是该类所属对象的字节码
if (s==null){ //如果引用为空
s = new.Single(); //则创建对象
}
}
}
return s; //返回对象引用
}
}
为了解决懒汉式单例设计模式多线程访问的问题,用双重判断加同步代码块,以解决其安全问题。
这种解决办法也存在一定的安全隐患,概率很低。