Java并发编程组件实例大全一:线程

线程

类结构

1
1
1
1
1
*
1
1
1
1
«interface»
Runnable
+run()
Thread
ThreadGroup
ThreadLocalMap
«enumeration»
State
NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED
SecurityManager
StackTraceElement
«interface»
UncaughtExceptionHandler
+uncaughtException(Thread t, Throwable e)
«interface»
Interruptible
interrupt(Thread var1)
ThreadLocal
类名说明
Thread线程类
RunnableRunnable接口应由其实例,将由线程执行的任何类实现。类必须定义一个名为run的无参数方法。此接口旨在为希望在激活时执行代码的对象提供通用协议。例如,Runnable由类线程实现。处于活动状态仅仅意味着线程已经启动,还没有停止。此外,Runnable提供了一种方法,使类在不子类化线程的情况下处于活动状态。通过实例化线程实例并将自身传递给目标,实现Runnable的类可以在不子类化Thread的情况下运行。在大多数情况下,如果只计划重写run()方法,而不打算重写其他线程方法,则应使用Runnable接口。这一点很重要,因为类不应该是子类,除非程序员打算修改或增强类的基本行为。
ThreadGroup线程组表示一组线程。此外,线程组还可以包括其他线程组。线程组形成一棵树,其中除初始线程组外的每个线程组都有一个父线程组。允许线程访问其自身线程组的信息,但不能访问其线程组的备用线程组或任何其他线程组的信息。
ThreadLocal此类提供线程局部变量。这些变量不同于它们的普通对应变量,因为访问一个变量的每个线程(通过其get或set方法)都有自己的、独立初始化的变量副本。ThreadLocal实例通常是希望将状态与线程(例如,用户ID或事务ID)关联的类中的私有静态字段。只要线程处于活动状态且ThreadLocalinstance可访问,每个线程都会持有对其线程localvariable副本的隐式引用;一个线程消失后,所有线程本地实例的副本都将接受垃圾收集(除非存在对这些副本的其他引用)。
ThreadLocalMapThreadLocalMap是一个定制的哈希映射,仅适用于维护线程本地值。没有操作导出到ThreadLocal类的外部。该类是包私有的,以允许在类线程中声明字段。为了帮助处理非常大且长期存在的用法,哈希表条目使用weakreference作为键。但是,由于不使用引用队列,因此只有当表开始耗尽空间时,才能保证删除过时的条目。
State线程的状态枚举。
1. NEW - 尚未启动的线程的线程状态。
2. RUNNABLE - 可运行线程的线程状态。处于可运行状态的线程正在Java虚拟机中执行,但它可能正在等待来自操作系统的其他资源,如处理器。
3. BLOCKED - 等待监视器锁定的被阻止线程的线程状态。处于阻止状态的线程正在等待监视器锁进入同步块/方法,或在调用Object.wait后重新输入同步块/方法。
4. WAITING - 等待线程的线程状态。由于调用以下方法之一,线程处于等待状态:Object.wait且没有超时;thread.join且没有超时;LockSupport.park。处于等待状态的线程正在等待另一个线程执行特定的操作行动。例如,调用Object.wait()的线程正在等待另一个线程调用该对象的Object.notify()或该对象上的Object.notifyAll()。一个线程调用Thread.join(),正在等待指定的线程终止。
5. TIMED_WAITING - 具有指定等待时间的等待线程的线程状态。由于使用指定的正等待时间调用以下方法之一,线程处于定时等待状态:
  • Thread.sleep
  • Object.wait(long) with timeout
  • Thread.join(long) with timeout
  • LockSupport.parkNanos
  • LockSupport.parkUntil

6.TERMINATED - 终止线程的线程状态。线程已完成执行。
Interruptible可中断接口。Thread将中断委派给此接口的实现类。
UncaughtExceptionHandler当线程由于未捕获异常而突然终止时调用的处理程序接口。当线程由于未捕获异常即将终止时,Java虚拟机将使用getUncaughtExceptionHandler查询线程的未捕获异常处理程序,并调用处理程序的suncaughtException方法,将线程和异常作为参数传递。如果线程未显式设置其UncaughtExceptionHandler,则其ThreadGroup对象充当其UncaughtExceptionHandler。如果ThreadGroup对象对处理异常没有特殊要求,它可以将调用转发到Thread.getDefaultUncaughtExceptionHandler
SecurityManager安全管理器是一个允许应用程序实现安全策略的类。它允许应用程序在执行可能不安全或敏感的操作之前,确定该操作是什么,以及是否在允许执行该操作的安全上下文中尝试该操作。应用程序可以允许或不允许该操作。SecurityManager类包含许多名称以单词check开头的方法。在这些方法执行某些潜在的敏感操作之前,Java库中的各种方法都会调用这些方法。这种检查方法的位置通常如下所示:SecurityManager security = System.getSecurityManager();security.checkXXX(…)

因此,安全管理器有机会通过抛出异常来防止操作完成。如果操作被允许,securitymanager例程只返回,如果操作不被允许,则返回SecurityException。此约定的唯一例外是checktoplevelwindow,它返回一个boolean值。
StackTraceElement|堆栈跟踪中的一个元素,由Throwable.getStackTrace()返回。每个元素表示一个堆栈帧。除了位于堆栈representa方法调用顶部的堆栈帧之外的所有堆栈帧。堆栈顶部的帧表示生成堆栈跟踪的执行点。通常,这是创建与堆栈跟踪对应的可丢弃项的点。

Thread

Thread是程序中的执行线程。

  • Java虚拟机允许应用程序同时运行多个执行线程。
  • 每个线程都有优先级。优先级较高的线程优先于优先级较低的线程执行。
  • 每个线程也可以标记为守护进程,也可以不标记为守护进程。
  • 当在某个线程中运行的代码创建新的thread对象时,新线程的优先级最初设置为等于创建线程的优先级,并且当且仅当创建线程是守护线程时,newthread才是守护线程。
  • 当Java虚拟机启动时,通常会有一个单一的非守护进程线程(它通常调用某个指定类的namedmain方法)。
  • Java VirtualMachine继续执行线程,直到发生以下任一情况:
  1. 调用了类Runtime的exit方法,并且安全管理器允许执行exit操作。
  2. 所有不是守护进程线程的线程都已死亡,要么是通过调用run方法返回,要么是通过抛出传播到run方法之外的异常。
成员变量说明
public final static int MIN_PRIORITY = 1The minimum priority that a thread can have.
public final static int NORM_PRIORITY = 5The default priority that is assigned to a thread.
public final static int MAX_PRIORITY = 10The maximum priority that a thread can have.
private Runnable target
private ThreadGroup group
private ClassLoader contextClassLoader
private static int threadInitNumber给匿名线程编号
ThreadLocal.ThreadLocalMap threadLocals保存线程本地变量,ThreadLocal变量作为map的key
hreadLocal.ThreadLocalMap inheritableThreadLocals
private long stackSizeThe requested stack size for this thread, or 0 if the creator did not specify a stack size. It is up to the VM to do whatever it likes with this number; some VMs will ignore it
private static long threadSeqNumber线程ID
private volatile int threadStatus线程状态
构造函数说明
public Thread()默认线程名称:Thread-n
public Thread(Runnable target)
public Thread(ThreadGroup group, Runnable target)
public Thread(String name)
public Thread(ThreadGroup group, String name)
public Thread(Runnable target, String name)
public Thread(ThreadGroup group, Runnable target, String name)
public Thread(ThreadGroup group, Runnable target, String name, long stackSize)
方法说明废弃原因
public static native Thread currentThread()Returns a reference to the currently executing thread object.
public static native void yield()A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.
public static native void sleep(long millis) throws InterruptedExceptionCauses the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors
public static void sleep(long millis, int nanos) throws InterruptedExceptionCauses the currently executing thread to sleep (temporarily ceaseexecution) for the specified number of milliseconds plus the specifiednumber of nanoseconds, subject to the precision and accuracy of systemtimers and schedulers. The thread does not lose ownership of anymonitors
public synchronized void start()Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread
public void run()
public final void stop()停止线程可能会导致未知的错误,建议改用变量控制使线程自然退出
public final synchronized void stop(Throwable obj)停止线程并抛出异常可能会导致未知的错误,建议改用变量控制使线程自然退出
public void interrupt()Interrupts this thread
public static boolean interrupted()Tests whether the current thread has been interrupted.重置中断标志位。
public boolean isInterrupted()Tests whether this thread has been interrupted
public void destroy()销毁线程调用此方法不会做清理工作,亦不会释放锁,可能会形成死锁
public final native boolean isAlive()Tests if this thread is alive. A thread is alive if it has been started and has not yet died
public final void suspend()挂起当前线程调用此方法不会释放锁,可能会形成死锁
public final void resume()恢复调用suspend()挂起的线程因为与suspend()配对使用
public final void setPriority(int newPriority)
public final int getPriority()
public final void setName(String name)
public final String getName()
public final ThreadGroup getThreadGroup()
public static int activeCount()估算当前线程的线程组及其子线程组中的活跃线程
public static int enumerate(Thread tarray[])将当前线程的线程组及其子线程组中的活跃线程放入数组
public native int countStackFrames()不建议使用。Counts the number of stack frames in this thread
public final synchronized void join(long millis)throws InterruptedExceptionWaits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
public final synchronized void join(long millis, int nanos) throws InterruptedException
public final void join() throws InterruptedException
public static void dumpStack()Prints a stack trace of the current thread to the standard error stream. This method is used only for debugging
public final void setDaemon(boolean on)Marks this thread as either a daemon thread or a user thread. The Java Virtual Machine exits when the only threads running are all daemon threads
public final boolean isDaemon()Determines if the currently running thread has permission to modify this thread.
public String toString()
public ClassLoader getContextClassLoader()
public void setContextClassLoader(ClassLoader cl)
public static native boolean holdsLock(Object obj)Returns true if and only if the current thread holds the monitor lock on the specified object.
public StackTraceElement[] getStackTrace()
public static Map<Thread, StackTraceElement[]> getAllStackTraces()
public long getId()
public State getState()
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)Set the default handler invoked when a thread abruptly terminates due to an uncaught exception, and no other handler has been defined for that thread.
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
public UncaughtExceptionHandler getUncaughtExceptionHandler()
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)

实例:运行一个线程的两种方式

package com.qupeng.concurrent.thread;

public class TestThread {
    public static void main(String[] args) {
        // 方式1:适用于需要对线程做配置的
        ThreadTest threadTest = new ThreadTest("ThreadTest");
        threadTest.run();

        // 方式2:适用于仅需要运行指定逻辑,而不需要配置线程的
        new Thread(new RunnableTest()).start();
    }

    public static class ThreadTest extends Thread {
        public ThreadTest(String name) {
            super(name);
        }

        @Override
        public void run() {
            System.out.println("Thread " + this.getName() + " is running.");
            System.out.println("Thread group: " + this.getThreadGroup().getName());
            System.out.println("Group active count: " + this.getThreadGroup().activeCount());
            System.out.println("Priority: " + this.getPriority());
            System.out.println("Id: " + this.getId());
            System.out.println("State: " + this.getState());
            System.out.println("Stack trace: " + this.getStackTrace());
            System.out.println("Is alive: " + this.isAlive());
        }
    }

    public static class RunnableTest implements Runnable {
        @Override
        public void run() {
            System.out.println("RunnableTest is running.");
        }
    }
}

实例:线程中断,join

package com.qupeng.concurrent.thread;

import java.util.concurrent.TimeUnit;

public class ThreadTest {
    public static void main(String[] args) {
        ThreadUtils.printStartingMessage();
        testThreadCreating();
        testInterrupt();
        testWaitNotification();
        ThreadUtils.printEndingMessage();
    }

    public static void testThreadCreating() {
        ThreadUtils.printThreadMessage("Started testing creating...");
        // 方式2:适用于仅需要运行指定逻辑,而不需要配置线程的
        Thread thread1 = new Thread(new MyRunnable(3, TimeUnit.SECONDS, true), "my-thread-1");
        thread1.start();

        // 方式1:适用于需要对线程做配置的
        MyThread thread2 = new MyThread("my-thread-2");
        thread2.start();
        try {
            thread1.join();
        } catch (InterruptedException e) {
        }
        try {
            thread2.join();
        } catch (InterruptedException e) {
        }
        ThreadUtils.printThreadMessage("Ended testing creating...");
    }

    public static void testInterrupt() {
        ThreadUtils.printThreadMessage("Started testing interrupt...");
        MyThreadFactory myThreadFacotry = new MyThreadFactory();
        Thread thread1 = myThreadFacotry.newThread(new MyRunnable());
        thread1.start();
        Thread thread2 = myThreadFacotry.newThread(new MyRunnable(2, TimeUnit.SECONDS, false));
        thread2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        thread1.interrupt();
        thread2.interrupt();
        try {
            thread1.join();
        } catch (InterruptedException e) {
        }
        try {
            thread2.join();
        } catch (InterruptedException e) {
        }
        ThreadUtils.printThreadMessage("Ended testing interrupt...");
    }

    public static void testWaitNotification() {
        ThreadUtils.printThreadMessage("Started testing wait & notification...");
        MyThreadFactory myThreadFacotry = new MyThreadFactory();
        Object blocker = new Object();
        Thread thread1 = myThreadFacotry.newThread(new MyRunnable(2, TimeUnit.SECONDS, true,blocker));
        thread1.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
        synchronized (blocker) {
            blocker.notify();
        }
        try {
            thread1.join();
        } catch (InterruptedException e) {
        }
        ThreadUtils.printThreadMessage("Ended testing wait & notification...");
    }
}

package com.qupeng.concurrent.thread;

import java.util.concurrent.TimeUnit;

public class MyRunnable implements Runnable {
    private long sleepingTime = 3000;
    private boolean isCancelable = true;
    private int executingTimes = 3;
    private Object blocker;

    public MyRunnable() {
    }

    public MyRunnable(long sleepingTime, TimeUnit timeUnit, boolean isCancelable, Object blocker) {
        this.sleepingTime = timeUnit.toMillis(sleepingTime);
        this.isCancelable = isCancelable;
        this.blocker = blocker;
    }

    public MyRunnable(long sleepingTime, TimeUnit timeUnit, boolean isCancelable) {
        this.sleepingTime = timeUnit.toMillis(sleepingTime);
        this.isCancelable = isCancelable;
    }

    @Override
    public void run() {
        ThreadUtils.printStartingMessage();
        ThreadUtils.printRunningMessage();

        if (null != blocker) {
            try {
                ThreadUtils.printWaitingMessage();
                synchronized (blocker) {
                    blocker.wait();
                }
            } catch (InterruptedException e) {
                ThreadUtils.printNotifideMessage();
            }
        }

        while (executingTimes-- > 0 && !Thread.currentThread().isInterrupted()) {
            try {
                ThreadUtils.printExecuingMessage();
                Thread.sleep(sleepingTime);
            } catch (InterruptedException e) {
                ThreadUtils.printInterruptedMessage();
                if (isCancelable) {
                    Thread.currentThread().interrupt();
                    ThreadUtils.printCanceledMessage();
                } else {
                    Thread.interrupted();
                }
            }
        }
        Thread.currentThread().interrupt();
        ThreadUtils.printEndingMessage();
    }
}
package com.qupeng.concurrent.thread;

public class MyThread extends Thread {
    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        ThreadUtils.printStartingMessage();
        ThreadUtils.printThreadInfo();
        ThreadUtils.printEndingMessage();
    }
}
package com.qupeng.concurrent.thread;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class MyThreadFactory implements ThreadFactory {
    private AtomicInteger atomicInteger = new AtomicInteger(1);
    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(Thread.currentThread().getThreadGroup(), r, "my-thread-" + atomicInteger.getAndIncrement());
        return thread;
    }
}
package com.qupeng.concurrent.thread;

import java.util.Arrays;

public class ThreadUtils {
    public static void printThreadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        try {
            int threadNumber = Integer.valueOf(threadName.substring(threadName.lastIndexOf('-') + 1));
            System.out.println(String.format("%" + threadNumber * 60 +"s%s", " ", message));
        } catch (NumberFormatException exception) {
            System.out.println(message);
        }

    }

    public static void printThreadInfo() {
        Thread thread = Thread.currentThread();
        printThreadMessage("Thread " + thread.getName() + " is running.");
        printThreadMessage("Thread group: " + thread.getThreadGroup().getName());
        printThreadMessage("Group active count: " + thread.getThreadGroup().activeCount());
        printThreadMessage("Priority: " + thread.getPriority());
        printThreadMessage("Id: " + thread.getId());
        printThreadMessage("State: " + thread.getState());
        printThreadMessage("Stack trace: " + thread.getStackTrace().toString());
        printThreadMessage("Active count: " + thread.activeCount());
        printThreadMessage("Is demon: " + thread.isDaemon());
        Object object = new Object();
        synchronized (object) {
            printThreadMessage("Holds lock: " + Thread.holdsLock(object));
        }
        printThreadMessage("Uncaught exception handler: " + thread.getUncaughtExceptionHandler());
        printThreadMessage("Context class loader: " + thread.getContextClassLoader());
        Thread[] tArray = new Thread[10];
        Thread.enumerate(tArray);
        printThreadMessage("enumerate: " + Arrays.toString(tArray));
        printThreadMessage("Is alive: " + thread.isAlive());
    }
    
    public static void printStartingMessage() {
        ThreadUtils.printThreadMessage(String.format("Thread %s started ...", Thread.currentThread().getName()));
    }

    public static void printRunningMessage() {
        ThreadUtils.printThreadMessage(String.format("Thread %s is running ...", Thread.currentThread().getName()));
    }

    public static void printInterruptedMessage() {
        ThreadUtils.printThreadMessage(String.format("Thread %s is interrupted ...", Thread.currentThread().getName()));
    }

    public static void printEndingMessage() {
        ThreadUtils.printThreadMessage(String.format("Thread %s ended ...", Thread.currentThread().getName()));
    }

    public static void printExecuingMessage() {
        ThreadUtils.printThreadMessage(String.format("Thread %s is executing ...", Thread.currentThread().getName()));
    }

    public static void printCanceledMessage() {
        ThreadUtils.printThreadMessage(String.format("Thread %s is canceled ...", Thread.currentThread().getName()));
    }

    public static void printWaitingMessage() {
        ThreadUtils.printThreadMessage(String.format("Thread %s is waiting ...", Thread.currentThread().getName()));
    }

    public static void printNotifideMessage() {
        ThreadUtils.printThreadMessage(String.format("Thread %s is notified ...", Thread.currentThread().getName()));
    }
}

ThreadLocal

方法说明
public T get()返回此线程局部变量的当前线程副本中的值。如果变量对于当前线程没有值,则首先将其初始化为调用{@link#initialValue}方法返回的值。
public void set(T value)将此线程局部变量的当前线程副本设置为指定值。大多数子类不需要重写此方法,只依赖{@link#initialValue}方法来设置线程局部变量的值。
public void remove()删除此线程局部变量的当前线程值。如果此线程局部变量随后被当前线程{@linkplain#get read}读取,则其值将通过调用其{@linkplain#initialValue}方法重新初始化,除非当前线程在此期间将其值设置为{@linkplain#set}。这可能会导致在当前线程中多次调用initialValue方法。

实例

package com.qupeng.concurrent.thread;

public class ThreadLocalTest {

    static ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        threadLocal.set("localVar0");
        Thread t1  = new Thread(new Runnable() {
            @Override
            public void run() {
                threadLocal.set("localVar1");
                System.out.println(String.format("Value of ThreadLocal in thread %s: %s", Thread.currentThread().getName(), threadLocal.get()));
                threadLocal.remove();
            }
        });

        Thread t2  = new Thread(new Runnable() {
            @Override
            public void run() {
                threadLocal.set("localVar2");
                System.out.println(String.format("Value of ThreadLocal in thread %s: %s", Thread.currentThread().getName(), threadLocal.get()));
                threadLocal.remove();
            }
        });
        System.out.println(String.format("Value of ThreadLocal in thread %s: %s", Thread.currentThread().getName(), threadLocal.get()));
        threadLocal.remove();
        t1.start();
        t2.start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值