线程的一些基本概念
一,创建线程的方式
* 方式一:继承Thread类 * 步骤: * 1.定义一个类继承Thread类 * 2.重写Thread类中的run 方法 * 3.直接创建Thread子类的对象 * 4.调用start方法开启线程并调用线程的任务run方法 * * * 可以通过Thread的getName获取线程的名称 Thread-编号(从0开始) * 主线程的名字是main * 可以通过Thread的currentThread方法 返回对当前正在执行的线程对象的引用 * * 方式二:实现 Runnable接口 * 1.定义类实现 Runnable接口 * 2.重写接口的run方法,将线程的任务代码封装到run方法中 * 3.通过 Thread类创建线程对象,并将Runnable接口的子类对象作为构造函数的参数进行传递 * 为什么? * 因为线程的任务都 封装在Runnable接口子类对象的run方法中 * 所以要在线程对象创建时就必须明确要运行的任务 * 4.调用线程对象的start方法开启线程 * * 两种方式的区别: * 方式二的好处:1.将线程的任务从线程的子类中分离出来 ,进行了单独的封装。将任务封装成对象 * 2.避免了java单继承的局限性 * * 所以方式二较为常用 二,多线程中的一些线程安全问题线程安全问题出现的原因: * 1.多个线程在操作共享的数据 * 2.操作共享数据 的线程代码有多余 * * 当一个线程在执行操作共享数据的多条代码过程中,其它线程参与了运算,就会导致线程安全问题的产生 * * 解决思路: * 就是将多条操作共享数据的线程代码封装起来,当有线程在执行运算这些代码的时候 ,其它线程是不可以参与运算的 * 必须要当前线程把这些代码都 执行完毕 后,其它 线程才可以参与 运算。 * * 在java 中,用同步代码块就可以解决这个问题 * 格式: * synchronized(对象){ * 需要被同步的代码 * } * 同步 的好处:解决了线程的安全问题 * 弊端:降低了效率,因为同步外的线程都会判断同步锁 * 同步 的前提 :同步中必须 有多个线程并使用同一个锁 */示例:/** * 同步函数的使用的锁是 this * 同步函数和同步代码块的区别: * 同步函数的锁是固定的 this * 同步代码块的锁是任意的对象。 * * 建议使用同步代码块, * ** 可以用 getClass方法获取 ,也可以用当前 类.class获取静态函数中因为没有this对象的引用,所以 * 静态的同步函数使用的锁是 该函数所属字节码文件对象,
*/class Tichet implements Runnable{
private static int num = 100;
Object object = new Object();
boolean flg = true;
@Override
public void run() {
if (flg) {
while (true) {
//注意 这里如果是静态的,则可以用 Tichet.class 或者 this.class
如果是非静态的,则可以直接用 this
synchronized (Tichet.class) {//同步代码块
if (num>0){
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()+"..obj..."+num--);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}else {
while (true) {
show();
}
}
}
public static synchronized void show(){//同步函数
if (num>0){
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()+"..function..."+num--);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class SynFunctionLock {
public static void main(String[] args){
Tichet tichet = new Tichet();Class clas = tichet.getClass();//这两种方式都是拿到当前对象的字节码文件
Class classs = Tichet.class;
Thread t1 = new Thread(tichet);
Thread t2 = new Thread(tichet);
t1.start();
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()+".....");
} catch (InterruptedException e) {
e.printStackTrace();
}
tichet.flg = false;
t2.start();
}
}