Java网络编程学习笔记(三)线程

来源:互联网 发布:中日关系现状 知乎 编辑:程序博客网 时间:2024/04/27 16:51

进程 & 线程

  • 进程就是在某种程度上相互隔离的、独立运行的程序。线程化是允许多个活动共存于一个进程中的工具。
  • 线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、程序计数器和局部变量。进程中的线程共享内存、文件句柄和其它每个进程应有的状态。
  • 进程可以支持多个线程,它们看似同时执行,但互相之间并不同步。尽管这让线程之间共享信息变得更容易,但必须确保每个线程不会妨碍同一进程里的其它线程。
  • 当服务器要处理成千上万个同时的连接时,可以使用轻量级的线程来处理连接,而不是重量级的进程。虽然每个单独的进程都有自己的一块内存,但线程在资源使用上更宽松,因为它们会共享内存。使用线程来代替进程,可以再让你的服务器性能提升三倍。再结合使用可重用的线程池(而不是可重用进程池),在同样的硬件和网络连接条件下,服务器的运行可以快9倍多!
  • 由于现代虚拟机和操作系统中线程可以提供很高的性能,而且构建一个基于线程的服务器相对简单,所以开始时总会考虑采用基于线程的设计。若确实遇到麻烦,应该考虑将应用分解到多个冗余的服务器上,而不要完全倚仗一个服务器上的3倍性能提升。

创建线程 & 结束线程

1.在Java中创建线程有下列两种方式:

  • 继承java.lang包下的Thread类,覆盖Thread类的run()方法,在run()方法中实现运行在线程上的代码。
new Thread() {    public void run() {}}.start();
  • 实现java.lang.Runnable接口,同样是在run()方法中实现运行在线程上的代码。
new Thread(new Runnable() {     public void run() {}}).start();

2.在Java中线程会以下列三种方式之一结束:

  • 线程到达其 run() 方法的末尾。
  • 线程抛出一个未捕获到的 Exception 或 Error。
  • 另一个线程调用一个弃用的 stop() 方法。弃用是指这些方法仍然存在,但是不应该在新代码中使用它们,并且应该尽量从现有代码中除去它们。

3.注意事项:

  • 多线程程序会在main()方法以及所有非守护线程(nondaemon
    thread)都返回时才退出(守护线程完成后台任务,如垃圾回收,它们并不阻止虚拟机退出)。
  • 实现Runnable接口不一定优于扩展Thread类。在一些特殊的情况下,在每个Thread对象的构造函数中调用Thread类的一些实例方法可能很有用。而这个类扩展另一个类,这种情况就必须使用Runnable接口。
  • 有些崇尚面向对象的人认为,线程完成的任务实际上不是一种Thread,因此应当放在一个单独的类或接口(如Runnable)中,而不应放在Thread的子类中。作者部分同意这种观点,但作者不认为这个观点像其声称的那样理由充分。

回调

1.一种简单有效的方法是,通过调用主类(即启动这个线程的类)中的一个方法来让线程告诉主程序它何时结束,这被称为回调(callback),因为线程在完成时反过来调用其创建者。这样一来,主程序就可以在等待线程结束期间休息,而不会占用运行线程的时间。
下面有两种方式:

  • 调用主类的静态方法。
  • 使用主类的实例方法。

2.注意事项:

  • 使用实例方法代替静态方法进行回调要复杂一些,但有很多优点。首先,它可以做到每个线程跟踪一个主类对象,而不需要额外的数据结构。此外,这个实例在必要时可以很容易地重新计算某个主类对象的摘要。
  • 在构造函数中启动线程很危险,特别是线程将回调原来的对象时。这里有一个竞态条件,可能会在构造函数结束而且对象完全初始化之前允许新线程进行回调。

同步

  • 为何要使用同步?

Java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据的不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程调用,从而保证了该变量的唯一性和准确性。

同步块

同步块,即有synchronized关键字修饰的语句块。 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。例如:

/** * 用同步块实现 * /synchronized(object) {    // 同步连续过程}

同步方法

1.由于用对象本身同步整个方法体是很常见的,所以Java为此提供了一个快捷方式。可以通过向方法声明添加synchronized修饰符,对当前对象(this引用)同步整个方法。例如:

/** * 用同步方法实现 * /public synchronized void fun() {    // 同步连续过程}

2.注意事项:

  • 同步方法使得很多VM的性能严重下降(不过更多最新的VM已经大为改进),可能会使代码速度降低三分之一或者更多。
  • 同步方法大大增加了死锁的可能。
  • 并不总是对象本身需要防止同时修改或访问,如果只是对该方法所属类的实例进行同步,可能并不能保护真正需要保护的对象。
  • 同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized代码块同步关键代码即可。
0 0
原创粉丝点击