Java多线程学习笔记
来源:互联网 发布:淘宝seo怎么优化关键词 编辑:程序博客网 时间:2024/06/05 09:13
Java多线程学习笔记
1、继承Thread类
实现多线程的常用方法就是继承Thread类,然后覆盖run()方法。下面是一个通过继承Thread类实现多线程的小例子:
import java.util.Date;public class ThreadTest extends Thread{ @Override public void run() { // 重写run方法 System.out.println(this.getName() + " " + new Date().toString()); } public static void main(String[] args) { // TODO Auto-generated method stub ThreadTest t1 = new ThreadTest(); t1.start(); ThreadTest t2 = new ThreadTest(); t2.start(); }}
运行结果如下:
Thread类实际上是Runnable接口的实现,
public class Thread implements Runnable { ...}
Thread类中,有一些方法比较常用:
线程在创建后,需要调用start()才能运行,然后线程会自动调用run()方法,所以在子类中需要覆盖run()方法。注意,我们要用start()来启动线程,run()方法仅仅是一个普通的方法。
sleep()和suspend()都可以让线程暂停执行,但是二者的区别如下:
(1).sleep()使线程休眠后,只能在时间结束后,线程才能恢复到就绪状态;而suspend()挂起线程后,可以通过resume()唤醒线程。
(2).另外,sleep()仅对当前线程起作用,而suspend()可以挂起另一个线程。yield()是一个静态的native方法,它的作用是“告诉当前正在执行的线程,把运行机会交给线程池中拥有相同优先级的线程”,说白了就是把机会留给别人。
stop()和interrupt()都可以中断线程,但二者区别在于stop强制终止线程,而interrupt()中断线程。关于二者的具体介绍,详见:http://blog.csdn.net/wxwzy738/article/details/8516253。这里插一句,如果我们要中断线程,最好设置一个共享变量,然后在run方法中,周期性地检查该变量的值,满足终止条件时再终止线程。
为了加深理解,现附上线程生命周期图(图片来自百度百科):
2、实现Runnable接口
Runnable接口的源码如下,只有一个抽象方法run(),因此实现这个接口的核心就是覆盖run()方法。
public interface Runnable { public abstract void run();}
下面是一个小例子,这个例子实现了Runnable接口
import java.util.Date;public class ThreadTest implements Runnable{ String name; ThreadTest(String name) { this.name = name; } @Override public void run() { System.out.println(this.name + " " + new Date().toString()); } public static void main(String[] args) { // TODO Auto-generated method stub ThreadTest t1 = new ThreadTest("Thread1"); new Thread(t1).start(); ThreadTest t2 = new ThreadTest("Thread2"); new Thread(t2).start(); }}
运行结果如下:
3、join方法
无join()时,主线程调用start()后,程序立即返回到主线程,此时主线程和子线程各运行各的,也就是我们常说的“异步”。
有join()时,主线程调用start()后,会一直等待子线程执行完毕,再往下执行,这也就是“同步”。
下面看两个小例子:
import java.util.Date;public class ThreadTest extends Thread{ @Override public void run() { while(true){ try { this.sleep(1000); System.out.println(this.getName() + " " + new Date().toString()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { // TODO Auto-generated method stub ThreadTest t1 = new ThreadTest(); t1.start(); ThreadTest t2 = new ThreadTest(); t2.start(); // 没有join() 直接返回到主线程 System.out.println("t1,t2 stop"); }}
运行结果显示,主线程在启动t1、t2两个子线程后,直接返回到主线程继续执行 System.out.println(“t1,t2
stop”);
下面我们加上join()方法,同时把while去掉,避免程序进入死循环无法返回。
import java.util.Date;public class ThreadTest extends Thread{ @Override public void run() { // 去掉了while(true)的循环 try { this.sleep(1000); System.out.println(this.getName() + " " + new Date().toString()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { // 注意要抛出异常 // TODO Auto-generated method stub ThreadTest t1 = new ThreadTest(); t1.start(); ThreadTest t2 = new ThreadTest(); t2.start(); t1.join(); // t1添加join() t2.join(); // t2添加join() System.out.println("t1,t2 stop"); }}
来看看效果吧,可以看到,程序直到t1、t2线程结束后,才返回执行System.out.println(“t1,t2 stop”);
4、synchronized关键字
synchronized知识点总结:
1、synchronized可以修饰代码块、对象和方法,不能用于修饰int、char、boolean等简单类型的变量。
synchronized int a = 0; // 错误,synchronized 不能修饰int类型变量
2、synchronized不能被继承。若父类中有一个方法使用了synchronized修饰,子类中覆盖了这个方法,子类中的这个方法默认不是同步的,必须加synchronized关键词显示地生命同步。
3、synchronized不能放在返回类型后面,比如下面这句代码就是错误的。
void synchronized func() // 错的,synchronized不能放在返回值后面
synchronized关键字可以修饰代码块:
class Test { private final static String key = ""; // 注意要设置为final synchronized(key) { // TODO 这里是同步的代码块 // 注意,这里不能改变key的值,否则不能同步 // 因此要把key设置为final }}
synchronized关键字也可以用来修饰方法,请看下面的例子:在单件模式中使用synchronized关键字。
5、用synchronized关键字实现单件模式
class Singleton { private static Singleton instance; private Singleton() { } // 使用synchronized 关键字修饰方法 public static synchronized Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; }}
当然,单件模式还有更简单的实现方式:
public class Singleton { private final static Singleton instance = new Singleton(); // 使用“急切” private Singleton() { } public static Singleton getInstance() { return instance; }}
6、实例:使用多线程打印数字
public class ThreadTest implements Runnable { private int num = 0; @Override public synchronized void run() { for(int i = 0; i < 10; i++) { System.out.println(this.num); num++; } } public static void main(String[] args) { // TODO Auto-generated method stub ThreadTest t1 = new ThreadTest(); new Thread(t1).start(); // 打印0-9 new Thread(t1).start(); // 打印10-19 new Thread(t1).start(); // 打印20-29 }}
程序的运行结果如下:
今天就到这里,拜~
- Java多线程学习笔记
- Java多线程学习笔记
- Java学习笔记---多线程
- java多线程学习笔记
- Java多线程学习笔记
- Java多线程学习笔记
- JAVA多线程学习笔记
- Java 多线程学习笔记
- java多线程学习笔记
- Java多线程学习笔记
- [学习笔记]Java多线程
- java多线程学习笔记
- Java多线程学习笔记
- Java学习笔记-多线程
- Java多线程学习笔记
- Java多线程学习笔记
- Java多线程学习笔记
- Java 多线程学习笔记
- 三角网格参数化几种简单的方法比较
- Unity3D之UI按键绑定事件(一)
- Scrapy+crontab 定时爬取小说更新推送到手机邮件
- cartographer源码分析(27)-io-points_batch.h
- 基于Python的开源人脸识别库:离线识别率高达99.38%——新开源的用了一下感受一下
- Java多线程学习笔记
- vb.net 教程 12-1 WebBrowser 3
- Eclipse环境安装Python插件PyDev
- cartographer源码分析(28)-io-points_processor.h
- 古文觀止卷七_原毁_韓愈
- 解决excel导出大数字溢出或者被科学计数法格式化
- cartographer源码分析(29)-io-min_max_range_filtering_points_processor.h
- Lucas–Kanade光流算法
- C++Windows下CONTAINING_RECORD宏的用法和详解