Java 中的多线程

最近使用了不少关于多线程的东西,现在有些时间了,就把多线程的知识总结一下。欢迎拍砖。

首先是创建一个线程的方式,大概有四种:

第一,继承 Thread 类并重写其中的 run 方法,然后实例化该类并调用 start 方法启动线程;

第二,实现 Runnable 接口并重写其中的 run 方法,然后将该类的实例作为 Thread 类的 target 创建一个 Thread 对象,调用 start 方法启动线程;

第三,实现 Callable 接口并重写其中的 call 方法,然后使用 FutureTask 包装实现了 Callable 接口的类的对象,接下来将 FutureTask 类的实例作为 Thread 类的 target 创建线程并调用 start 方法启动线程;

第四,调用 Executors 的静态方法创建一个线程池,然后使用返回的 ExecutorService 对象的 submit 方法将 Runnable 或 Callable 的实现类实例提交给线程池运行。

以上四种方式中,第一种方式是最基本的,第二种与第三种方式最终仍是创建了一个 Thread 类的对象,而最后一种方式通过线程池来实现性能的提高。

第一种方式由于所采取的是继承 Thread 类,这也就导致了无法再继承其他类,因此在灵活性上逊色于第二种方式,并且对于资源的共享而言,在子类中定义的实例属性无法共享,安全固然安全,但也带来了不便,甚至一定意义上失去了多线程的价值——共享数据。

第二种方式较常使用(^o^反正小菜我总是使用这种方式),重写的 run 方法作为线程执行体当调用 start 方法后开始处于就绪状态。这种方式由于使用的是实现 Runnable 接口,故而弥补了 Java 的单重继承,但最后仍是作为 Thread 类的一个参数由 Thread 类的实例来执行线程,这也说明了在 Java 中是使用 Thread 类来代表线程,所有的线程对象都必须是 Thread 类或其子类的实例。

第三种方式的优势是可以在线程执行完毕后得到一个返回值,并且能够声明抛出异常(是对于 call 方法而言),而重写 run 方法则不允许如此 "乱来"。

最后一种实现方式非常方便,而且提高了性能,在对于线程的使用非常频繁的地方运用。

注意点:

1,不能妄图直接调用 run 方法或 call 方法而启动一个线程,这样做的效果与调用普通方法是一样的,最终是在主线程执行方法,而不会创建一个子线程。

2,可以使用 Thread 类的实例方法 getName 来取得一个线程的名字,当没有通过 setName 方法设置线程名字(或没有在创建线程时传入一个代表线程名字的字符串)时,默认情况下主线程名为 "main" ,子线程依次命名为 "Thread-0"、"Thread-1" 等,需要注意的是,在继承自 Thread 类的子类中获得当前线程的名字时可以直接使用 getName 方法,而在其他情形下要想获得线程的名字,必须使用 "Thread.currentThread().getName()" 这种方式。

接下来是对于线程的控制,在 Java 中使用以下函数完成对线程的控制:

两个 Thread 类中的静态方法

① sleep  ② yield

一个实例方法

① join

当然还有其他方法,比如 stop、suspend、resume 等,但一般不使用。而以上三个方法中,第一个方法可以让当前处于运行状态的线程进入阻塞状态,从而让其他的线程得以执行,该方法的参数指定处于阻塞状态的时间,时间过后线程会重新回到就绪状态等待下一次执行;而 yield 方法只会让当前线程处于就绪状态,这也就是说当前线程仍可能被继续执行,当程序中的其余线程优先级低于当前线程时,调用该方法起不到预期效果,这时可以使用 setPriority 方法设置线程的优先级,也就是说,yield 方法只会给优先级等于或高于调用线程的线程以执行的机会。join 方法会使调用它的线程执行完之后再执行处于调用语句之后的代码。

最后是线程安全问题。多线程使得资源的共享更为方便,尤其是采用后面三种创建线程的方法,同时也使得线程的安全性得不到保障。多条线程对于共享数据的随机修改会造成严重的程序逻辑错误,这是因为一旦线程创建并启动,各个线程之间的地位是完全相等的,不受创建它的线程影响。Java 中采用如下方式保证线程的安全性:

①同步代码块  ②同步方法  ③同步锁

其中同步代码块可以使用任一对象作为同步监视器,而同步方法默认使用当前对象作为同步监视器,同步锁则使得线程安全的操作更灵活。其实本质上这三者的思路都是相同的,都是使对于竞争资源的访问遵循先加锁才能访问,使用结束就放锁,以便其他线程获得锁进而访问该资源。

当然多线程还有关于死锁、通信等内容,说来惭愧,对此不熟悉,就不在各位关公面前耍大刀了。总之,多线程使得程序的结构更加理想,是程序中不可缺少的部分。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章