- Thread.currentThread()//获取当前线程对象(Thread类型)
- Thread.currentThread().getName() //获取当前线程名字.
- 创建线程的第一种方式:继承Thread类。
- 步骤:1.继承Thread类,并重写Run()方法
- 2.需要几个线程,就创建几个子类对象(容易造成多次加载子类中的成员变量)
- 3.调用Start()方法开启
- 4.关闭线程有两种,
- 一种是Thread.Stop(),另一种是Thread.interrupt()方法,使用时使用后者,因为Stop()太暴力,会直接终止线程,后面的程序根本不能运行.而interrupt()方法则会终止当前线程后抛出一个异常出来,然后会执行到后面的代码.
- 创建线程的第二种方式:实现Runnable接口。
- 万一子类已经有了继承,那么Thread方法就没有办法实现,只能用Runnable方法;
- 区别:Thread方法是继承关系,运行时调用子类的Run方法,同时子类的Run方法受成员变量(不加static)的影响,每次启动线程都需要执行一次(每次创建一个线程,都要去创建一个子类对象,然后调用run方法,每创建一个子类,子类如果有成员变量就加载一次,很麻烦)
- runnable方法只是封装了run方法,在调用时需要创建一次子类对象,然后把子类对象传入需要的thread线程的构造方法的参数中.传入runnable的值,只调用run方法,不涉及每次都读取其他成员.
- 利用runnable接口创建线程步骤:
- 1,定义类实现Runnable接口。
- 2,覆盖接口中的run方法,将线程的任务代码封装到run方法中。
- 3,通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。
- (为什么?因为线程的任务都封装在Runnable接口子类对象的run方法中。
- 所以要在线程对象创建时就必须明确要运行的任务。)
- 4,调用线程对象的start方法开启线程。
- 实现Runnable接口的好处:
- 1,将线程的任务从线程的子类中分离出来,进行了单独的封装。
- 按照面向对象的思想将任务的封装成对象。
- 2,避免了java单继承的局限性。
- 所以,创建线程的第二种方式较为常用。
- 创建线程的第三种步骤: 利用线程池实现callable接口(需要返回值时可以用)
- 步骤:1.创建线程池ExecutorService pool = Executors.newFixedThreadPool(2);
- 2.创建一个子类实现callable接口,需要返回值时标明类型
- 3.调用线程池的方法创建实现子类对象pool.submit(子类实现对象);
- 4.调用get()方法获取返回值
- 解决线程安全问题:同步代码块
- synahronized(必须有参数,想为空就随便调用一个类,例如Object){
- }
- Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块。
- synahronized的三种用法
- 1.方法声明时使用,放在范围操作符(public等)后,其返回类型声明(void等)之前。即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入。
- 例如:
- public synchronized void synMethod() {
- //方法体
- }
- 2.对某一代码块使用,synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块。例如:
- public int synMethod(Object a1){
- synchronized(Object) {
- //一次只能有一个线程进入
- }
- }
- 3.synchronized后面括号里是一对象,此时,线程获得的是对象锁。
-
- 多线程理解
复制代码
|
|