对线程的理解
线程是比进程的一条执行路线,当我们启动一个应用软件时,其实系统会为它分配一个进程,而大部分软件是支持多线程的,可以在一个程序内部同时执行多项不同的任务,也有的单线程的。比如我们使用安全卫士,可以扫描病毒的同时,可以清理系统垃圾,还可以修补系统漏洞等等。这些就是多线程的典型应用。
Java中自定义线程
继承Thread类自定义线程
我们可以通过继续Thread类来自定义自己的线程,并且重写Thread中的run()方法,把要线程执行的语句写到run()方法中。然后我们可以通过调用自定义的Thread中的start()方法来启动一个线程,而不是执行调用run()方法。
同时我们还需要注意:我们不同让同一个对象多次调用start()方法,要想开启多个线程,需要重新new一个对象,再去调用start()方法。
如果需要给线程自定义一个名字,我们可以调用Thread中的setName(String name)方法给命名,当我们想要获取当下正在运行的线程的时候我们可以调用getName()方法。
通过实现Runnable接口的方式自定义线程
实现Runnable接口,同时需要实现该接口下的run()方法,把要线程执行的语句,写到run()方法里面。当我们需要启动一个线程时还是要通过Thread的实例去调用start()方法,不同的是,我们需要在Thread的构造器中传过来Runnable的实例。
代码如下:
Runnable r - new MyRunnable();
r.start(); // 这是错误的写法
// 正确写法如下
Thread t = new Thread(r);
t.start();
通过实现Callable接口的方式自定义线程
通过实现Callable接口的方式中,我们需要实现该接口中的call()方法,并且该方法有返回值,可以抛出异常,比前两种方式更加强大,更加复杂,是JDK 5的时候新增的。
当我们想要获取call()方法的返回值时,我们需要借助FutureTask类的get()方法,该方法的返回值即为call()方法的返回值。
当我们想要开启一个线程时,也不是让Callable去调用start()方法,也没有该方法可以调用,而是我们需要创建FutureTask类的对象,把该对象传递到Thread的构造器中,在这之前需要给FutureTask的构造器中传递Runnable的实现类或Callable的实现类,当我们想要开启一个线程时调用Thread类中的start()方法即可。
代码如下:
public static void main(String[] args) {
MyCallable myCallable = new MyCallable();
FutureTask futureTask = new FutureTask(myCallable);
Thread t = new Thread(futureTask);
t.start();
try {
Object sum = futureTask.get();
System.out.println(sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
还可以通过线程池的方式创建多线程
通过Executors类中的四个常用的静态方法的调用,可以创建定长的线程池,定时线程池,单线程化的线程池,可缓存线程池。
代码如下:
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.submit(new MyRunnable1());
executorService.submit(new MyRunnable2());
executorService.shutdown();
}
Q.E.D.