创建线程的方式 创建线程共有两种方式:继承方式和实现方。 1、 继承方式 创建步骤: a,定义类继承Thread。 b,复写Thread中的run方法。 目的:将自定义代码存储在run方法中,让线程运行。 c,创建定义类的实例对象。相当于创建一个线程。 d,用该对象调用线程的start方法。该方法的作用是:启动线程,调用run方法。 注:如果对象直接调用run方法,等同于只有一个线程在执行,自定义的线程并没有启动。 覆盖run方法的原因: Thread类用于描述线程。该类就定义了一个功能,用于存储线程要执行的代码。该存储功能就run方法。也就是说,Thread类中的run方法,用于存储线程要运行的代码。 2、 实现方式 使用继承方式有一个弊端,那就是如果该类本来就继承了其他父类,那么就无法通过Thread类来创建线程了。这样就有了第二种创建线程的方式:实现Runnable接口,并复习其中run方法的方式。 创建步骤: a,定义类实现Runnable的接口。 b,覆盖Runnable接口中的run方法。目的也是为了将线程要运行的代码存放在该run方法中。 c,通过Thread类创建线程对象。 d,将Runnable接口的子类对象作为实参传递给Thread类的构造方法。 为什么要将Runnable接口的子类对象传递给Thread的构造函数? 因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定对象的run方法,就必须明确该run方法所属对象。 e,调用Thread类中start方法启动线程。start方法会自动调用Runnable接口子类的run方法。 实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。 线程安全问题解决办法——同步(同步代码块或者同步函数) 对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。 在java中对于多线程的安全问题提供了专业的解决方式——synchronized(同步) 这里也有两种解决方式,一种是同步代码块,还有就是同步函数。都是利用关键字synchronized来实现。 a、同步代码块 用法: synchronized(对象) {需要被同步的代码} 同步可以解决安全问题的根本原因就在那个对象上。其中对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
b,同步函数 格式: 在函数上加上synchronized修饰符即可。 那么同步函数用的是哪一个锁呢? 函数需要被对象调用。那么函数都有一个所属对象引用。就是this。所以同步函数使用的锁是this。
静态函数的同步方式 如果同步函数被静态修饰 因为静态方法中也不可以定义this。静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。 类名.class 该对象的类型是Class 这就是静态函数所使用的锁。而静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class 停止线程 1、开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。 如:run方法中有如下代码,设置一个flag标记。 那么只要在主函数或者其他线程中,在该线程执行一段时间后,将标记flag赋值false,该run方法就会结束,线程也就停止了。 2、上面的1方法可以解决一般情况,但是有一种特殊情况:就是当线程处于冻结状态。就不会读取到标记。那么线程就不会结束。 当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。Thread类提供该方法interrupt();
其他小方法 1、join方法 当A线程执行到了b线程的.join()方法时,A线程就会等待,等B线程都执行完,A线程才会执行。(此时B和其他线程交替运行。)join可以用来临时加入线程执行。 2、setPriority()方法用来设置优先级 MAX_PRIORITY 最高优先级10 MIN_PRIORITY 最低优先级1 NORM_PRIORITY 分配给线程的默认优先级 3、yield()方法可以暂停当前线程,让其他线程执行。
|