多线程(三) java中线程的简单使用

=============================================

原文链接:多线程(三) java中线程的简单使用 转载请注明出处!

=============================================

java中,启动线程通常是通过Thread或其子类通过调用start()方法启动。
 常见使用线程有两种:实现Runnable接口和继承Thread。而继承Thread亦或使用TimerTask其底层依旧是实现了Runnabel接口。考虑到java的单继承的限制,所以在开发过程中大部分情况在使用线程的时候是通过实现Runnabel接口或者Runnbel匿名类来实现的。
 例如:

package com.zpj.thread.blogTest;
/**
 * Created by PerkinsZhu on 2017/8/11 16:42.
 */
public class ThreadTest {

    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        //所有的这些启动方式的执行体都是在run方法中完成的
        threadTest.testLambda();
        threadTest.testRunnableWithAnonymousRunnable();
        threadTest.testRunnableWithAnonymousThread();
        threadTest.testRunnable();
        threadTest.testMyThread();
    }

    public void testLambda() {//lambda表达式开启线程 jdk1.8中的特性
        new Thread(() -> System.out.println("i am lambda Thread....")).start();
    }

    public void testRunnableWithAnonymousThread() {//匿名Thread类开启线程
        new Thread() {
            @Override
            public void run() {
                System.out.println("i am ThreadWithAnoymous");
            }
        }.start();
    }

    public void testRunnableWithAnonymousRunnable() {//匿名Runnable类开启线程
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("i am RunableWithAnoymous");
            }
        });
        thread.start();
    }

    public void testRunnable() {//实现Runnable接口
        MyRunnable runable = new MyRunnable();
        Thread thread = new Thread(runable);
        thread.start();
    }

    public void testMyThread() {//继承自Thread
        MyThread thread = new MyThread();
        thread.setName("MyThread");
        thread.start();
    }
}

class MyRunnable implements Runnable {//实现Runnable接口

    @Override
    public void run() {
        System.out.println("i am MyRunnable");
    }
}

class MyThread extends Thread {//继承Thread

    @Override
    public void run() {
        System.out.println(" i am MyThread!!");
    }
}

注意,直接调用run()方法的方式执行线程体并未开启新线程,只是在main方法中调用了一个普通方法而已。而使用start()方法则会开启一个新的线程执行。两者的区别主要表现在前者是阻塞式的,而后者为非阻塞式。

例如:

    public void testStartAndRun(){
        MyThread thread = new MyThread();
        thread.setName("MyThread");
        thread.start();//start启动两者异步非阻塞运行
        while (true){
            System.out.println("---- "+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
class MyThread extends Thread {//继承Thread

    @Override
    public void run() {
        while(true){
            System.out.println("=== "+Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:

---- main==== MyThread---- main==== MyThread==== MyThread---- main==== MyThread---- main

而把thread.start() 修改为thread.run();之后,则如下

==== main
==== main
==== main
==== main
==== main
==== main

这里之所以线程名称为main是因为是在main线程中调用的run方法,所以打印出来的是===main。而thread.run();语句下面的循环则永远不会执行,程序将会一直在run方法中循环下去。

那么调用start方法,程序都做了些什么呢?看一下底层实现。

    public synchronized void start() {
        //验证线程的状态
        if (threadStatus != 0) {//这里的验证涉及到线程不能重复启动的问题,线程多次调用start则会抛出该异常
            throw new IllegalThreadStateException();
        }
        //把该线程加入到线程组中
        group.add(this);
        boolean started = false;//标识线程是否启动成功
        try {
            start0();//调用native方法启动线程 该方法是阻塞的,程序等待其完成之后执行下面语句如果执行失败则直接抛出异常进入finally。
            started = true;//修改线程启动状态
        } finally {
            try {
                if (!started) {//启动失败,则移出线程组
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
            }
        }
    }

private native void start0();//native方法启动线程

通过Runnable启动具有一定的局限,执行线程没有返回值,无法捕获异常。在有些特殊情况下需要线程返回结果的时候就不太合适。这时可以选择Callable接口来完成。Callable涉及到Future模型,这到后面再说。

-----end

时间: 2024-10-26 21:24:34

多线程(三) java中线程的简单使用的相关文章

学习笔记3: java中线程的简单实现

附上代码段: public class DemoThread3 { /**  * @author 牧羊的伯格女皇  * @param args  * 2015-10-15  * 模拟猫和狗的线程,共享房屋中的一桶水.即房屋是线程的目标对象.  * 当水被喝完后 猫和狗 进入死亡状态   */ public static void main(String[] args) { House house = new House(); house.setWaterAmount( 10 ); Thread 

Java中线程(Thread)知识概括

Java中线程(Thread)知识概括 进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行. 一个进程中至少有一个线程. 例如:Java VM 启动的时候会有一个进程java.exe.该进程中至少一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中.该线程称之为主线程.jvm启动不止一个线程,还有负责垃圾回收机制等线程. 如何在自定义的代码中,自定义一个线程呢

Java中线程同步的理解 - 其实应该叫做Java线程排队

Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程"同步"机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize(使同时发生)翻译过来的.我也不明白为什么

Java中线程顺序执行

现有线程threadone.threadtwo和threadthree,想要的运行顺序为threadone->threadtwo->threadthree,应该如何处理?这里需要用到一个简单的线程方法join(). join()方法的说明:join方法挂起当前调用线程,直到被调用线程完成后在继续执行(join() method suspends the execution of the calling thread until the object called finishes its ex

Java中线程的实现:

Java中线程的实现: 一.线程简介: 实现的两种方式为: 1.Thread类 2.Runnable接口 都在java.lang中 都有共通的方法:public void run() 二.线程常用方法 线程启动:start() 线程睡眠:sleep() 线程抢占:join() 线程让步:yield() 三.线程实例 实例一:Thread类实现 class Xc extends Thread   //创建线程所需要继承的类 { public void run()            //run方

java中线程池

在jdk1.5中加入了java.util.concurrent,这个包中主要介绍java中线程以及线程池的使用 现在看怎么创建一个线程池,在java中Executors类创建线程池的,而线程池分为三类, 1:Executors.newFixedThreadPool(3);//这是固定的线程池 2: Executors.newCachedThreadPool();创建一个带缓存的线程池,比如创建了3个线程在线程池中,但是现在有10个线程在执行任务,因此它还会创建7个线程 3:Executors.n

Java中线程封闭之ThreadLocal

在访问共享数据时通常使用同步.若不使用同步则可以将对象封闭在一个线程中达到线程安全的目的,该方法称为线程封闭(Thread Confinement).其中实现线程封闭中规范的方法是使用ThreadLocal类.线程封闭技术一种常用的使用场景是在JDBC Connection对象. public class ConnectionHelper{private final static String URL = "";private final static ThreadLocal<C

java中,一个简单但出错率又大的‘加法’题,1+1+&#39;1&#39;+1+1+1+1+&quot;1&quot;=?

1+1+'1'+1+1+1+1+"1"=? 结果是多少?很多人看了题之后,可能会说结果是71.  当然有的童鞋可能会说很简单,放工具里运行一下就知道结果了,如果不运行代码,你会得出一个什么样的结果呢? 如果告诉你答案是551,会迷惑么?怎么会得出551? 下面我们来看看怎么算的: 1.我们大家都知道1 .'1'."1"的区别,1 表示一个int类型,’1'是表示一个char类型,"1" 表示一个字符串类型. 2.1+1+'1'+1+1+1+1+&

java中线程存活和线程执行的问题!

1 /* 2 下面的程序会出现下面的情况,当Thread-0, Thread-1, Thread-2都被wait的时候,可能会同时苏醒 3 Thread-0 put 4 Thread-1 put 5 Thread-2 put 6 Thread-3 get//在此处,Thread-3拿到锁之后,将所有的等待的线程唤醒,才有了下面的输出 7 Thread-2 put 8 Thread-1 put 9 Thread-0 put 10 */ 11 12 13 虽然多个线程会同时苏醒,但是只有一个能获得c