【高并发系列】3、线程那些事儿

本文深入探讨Java线程的高级操作,包括线程的创建、生命周期管理、中断处理、同步控制、线程间通信及资源竞争解决方案。通过具体代码示例,详细解析线程的正确停止、中断响应、wait和notify机制、suspend与resume替代方案,以及join和yield的使用技巧。

线程是轻量级进程,是程序执行的最小单位;

线程的生命周期:

线程基本操作:

1、新建线程

Thread t = new Thread();
t.start();

Thread的run()方法只会在当前线程中串行执行run()方法中的代码,正确开启新线程应使用start()方法;

public class CreateThread implements Runnable {

	@Override
	public void run() {
		System.out.println("CreateThread.run()");
	}

	public static void main(String[] args) {
		Thread t = new Thread(new CreateThread());
		t.start();
	}

}

默认的Thread.run()方法就是直接调用内部Runnable接口;

/* What will be run. */
private Runnable target;

/**
 * If this thread was constructed using a separate
 * <code>Runnable</code> run object, then that
 * <code>Runnable</code> object's <code>run</code> method is called;
 * otherwise, this method does nothing and returns.
 * <p>
 * Subclasses of <code>Thread</code> should override this method.
 *
 * @see     #start()
 * @see     #stop()
 * @see     #Thread(ThreadGroup, Runnable, String)
 */
@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

2、终止线程

stop()方法之所以被废弃,是因为stop()方法过于暴力,强行把正在执行的线程终止,可能会引起一些数据不一致的问题;

不安全的停止线程demo:

public class StopThreadUnsafe {
	private static User u = new User();
	public static class User {
		private int id;
		private String name;
		public User() {
			id = 0;
			name = "0";
		}
		public void setId(int id) {
			this.id = id;
		}
		public int getId() {
			return id;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getName() {
			return name;
		}
		@Override
		public String toString() {
			return "User [id=" + id + ", name=" + name + "]";
		}
	}
	public static class ChangeObjectThread extends Thread {
		@Override
		public void run() {
			while (true) {
				synchronized (u) {
					int v = (int) (System.currentTimeMillis() / 1000);
					u.setId(v);
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					u.setName(String.valueOf(v));
				}
				Thread.yield();
			}
		}
	}
	public static class ReadObjectThread extends Thread {
		@Override
		public void run() {
			while (true) {
				synchronized (u) {
					if (u.getId() != Integer.parseInt(u.getName())) {
						System.out.println(u);
					}
				}
				Thread.yield();
			}
		}
	}
	@SuppressWarnings("deprecation")
	public static void main(String[] args) throws InterruptedException {
		new ReadObjectThread().start();
		while (true) {
			Thread t = new ChangeObjectThread();
			t.start();
			Thread.sleep(150);
			t.stop();
		}
	}
}

##################################################
console
User [id=1549372735, name=1549372734]
User [id=1549372735, name=1549372734]
User [id=1549372735, name=1549372734]
User [id=1549372736, name=1549372735]

正确停止线程demo:

public class StopThreadSafe {
	private static User u = new User();
	public static class User {
		private int id;
		private String name;
		public User() {
			id = 0;
			name = "0";
		}
		public void setId(int id) {
			this.id = id;
		}
		public int getId() {
			return id;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getName() {
			return name;
		}
		@Override
		public String toString() {
			return "User [id=" + id + ", name=" + name + "]";
		}
	}
	public static class ChangeObjectThread extends Thread {
		private volatile boolean stopme = false;
		public void stopMe() {
			stopme = true;
		}
		@Override
		public void run() {
			while (true) {
				if (stopme) {
					System.out.println("exit by stop me");
					break;
				}
				synchronized (u) {
					int v = (int) (System.currentTimeMillis() / 1000);
					u.setId(v);
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					u.setName(String.valueOf(v));
				}
				Thread.yield();
			}
		}
	}
	public static class ReadObjectThread extends Thread {
		@Override
		public void run() {
			while (true) {
				synchronized (u) {
					if (u.getId() != Integer.parseInt(u.getName())) {
						System.out.println(u);
					}
				}
				Thread.yield();
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		new ReadObjectThread().start();
		while (true) {
			ChangeObjectThread t = new ChangeObjectThread();
			t.start();
			Thread.sleep(150);
			t.stopMe();
		}
	}
}

#####################
console
exit by stop me
exit by stop me
exit by stop me

3、线程中断

线程中断是一种重要的线程协作机制;

public void interrupt()                // 中断线程
public boolean isInterrupted()         // 判断是否被中断
public static boolean interrupted()    // 判断是否被中断,并清除当前中断状态
public void interrupt() {
    if (this != Thread.currentThread())
        checkAccess();
    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0();
}
public boolean isInterrupted() {
    return isInterrupted(false);
}
public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}
/**
 * Tests if some Thread has been interrupted.  The interrupted state
 * is reset or not based on the value of ClearInterrupted that is
 * passed.
 */
private native boolean isInterrupted(boolean ClearInterrupted);

 使用Thread.currentThread().isInterrupted()判断当前线程是否被中断,如果被中断了,退出循环体,结束线程;

public class InterruptThread {
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread("interrupt") {
			@Override
			public void run() {
				while (true) {
					if (Thread.currentThread().isInterrupted()) {
						System.out.println("Interrupted!");
						break;
					}
				}
				Thread.yield();
			}
		};
		t.start();
		TimeUnit.SECONDS.sleep(2);
		t.interrupt();
	}
}

Thread.sleep()函数签名:

/**
 * Causes 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.
 *
 * @param  millis
 *         the length of time to sleep in milliseconds
 *
 * @throws  IllegalArgumentException
 *          if the value of {@code millis} is negative
 *
 * @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.
 */
public static native void sleep(long millis) throws InterruptedException;

当线程在休眠被中断时会抛出InterruptedException异常,并清除中断标记,catch捕获后没有选择立即退出线程,而是设置中断标志,保证数据的一致性和完整性; 

public class InterruptSleepThread {
	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread("interrupt-sleep") {
			@Override
			public void run() {
				while (true) {
					if (Thread.currentThread().isInterrupted()) {
						System.out.println("Interrupted!");
						break;
					}
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						System.out.println("Interrupted when sleep.");
						// 设置中断状态
						Thread.currentThread().interrupt();
					}
				}
				Thread.yield();
			}
		};
		t.start();
		Thread.sleep(1500);
		t.interrupt();
	}
}

4、等待wait()和通知notify()

public final native void wait(long timeout) throws InterruptedException
public final native void notify()
public final native void notifyAll()

Object.wait()方法和Thread.sleep()方法都让线程等待若干时间,wait()方法可以被唤醒,并且wait()方法会释放目标对象的锁,但sleep()方法不会释放任何资源;

public class WaitNotifyDemo {
	private static final Object lock = new Object();
	public static class WaitThread extends Thread {
		@Override
		public void run() {
			synchronized (lock) {
				System.out.println(System.currentTimeMillis() + ":WaitThread start!");
				try {
					System.out.println(System.currentTimeMillis() + ":WaitThread wait for lock.");
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(System.currentTimeMillis() + ":WaitThread end!");
			}
		}
	}
	public static class NotifyThread extends Thread {
		@Override
		public void run() {
			synchronized (lock) {
				System.out.println(System.currentTimeMillis() + ":NotifyThread start!");
				lock.notify();
				System.out.println(System.currentTimeMillis() + ":NotifyThread end!");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	public static void main(String[] args) {
		Thread waitThread = new WaitThread();
		Thread notifyThread = new NotifyThread();
		waitThread.start();
		notifyThread.start();
	}
}

1549382736972:WaitThread start!
1549382736972:WaitThread wait for lock.
1549382736972:NotifyThread start!
1549382736972:NotifyThread end!
1549382738977:WaitThread end!

5、挂起suspend()和继续执行resume()线程

/**
 * Suspends this thread.
 * <p>
 * First, the <code>checkAccess</code> method of this thread is called
 * with no arguments. This may result in throwing a
 * <code>SecurityException </code>(in the current thread).
 * <p>
 * If the thread is alive, it is suspended and makes no further
 * progress unless and until it is resumed.
 *
 * @exception  SecurityException  if the current thread cannot modify
 *               this thread.
 * @see #checkAccess
 * @deprecated   This method has been deprecated, as it is
 *   inherently deadlock-prone.  If the target thread holds a lock on the
 *   monitor protecting a critical system resource when it is suspended, no
 *   thread can access this resource until the target thread is resumed. If
 *   the thread that would resume the target thread attempts to lock this
 *   monitor prior to calling <code>resume</code>, deadlock results.  Such
 *   deadlocks typically manifest themselves as "frozen" processes.
 *   For more information, see
 *   <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 *   are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 */
@Deprecated
public final void suspend() {
    checkAccess();
    suspend0();
}

/**
 * Resumes a suspended thread.
 * <p>
 * First, the <code>checkAccess</code> method of this thread is called
 * with no arguments. This may result in throwing a
 * <code>SecurityException</code> (in the current thread).
 * <p>
 * If the thread is alive but suspended, it is resumed and is
 * permitted to make progress in its execution.
 *
 * @exception  SecurityException  if the current thread cannot modify this
 *               thread.
 * @see        #checkAccess
 * @see        #suspend()
 * @deprecated This method exists solely for use with {@link #suspend},
 *     which has been deprecated because it is deadlock-prone.
 *     For more information, see
 *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 *     are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 */
@Deprecated
public final void resume() {
    checkAccess();
    resume0();
}

suspend()方法挂起线程时导致线程暂停,但不会释放任何锁资源;如果resume()方法意外地在suspend()方法前就执行了,会导致被挂起的线程可能很难有机会被继续执行;并且对于被挂起的线程,从线程状态上看居然还是Runnable;

public class SuspendResumeDemo {
	public static Object lock = new Object();
	private static ChangeObjectThread t1 = new ChangeObjectThread("t1");
	private static ChangeObjectThread t2 = new ChangeObjectThread("t2");
	public static class ChangeObjectThread extends Thread {
		public ChangeObjectThread(String name) {
			super.setName(name);
		}

		@SuppressWarnings("deprecation")
		@Override
		public void run() {
			synchronized (lock) {
				System.out.println("In " + getName());
				Thread.currentThread().suspend();
			}
		}
	}
	@SuppressWarnings("deprecation")
	public static void main(String[] args) throws InterruptedException {
		t1.start();
		Thread.sleep(100);
		t2.start();
		t1.resume();
		t2.resume();
		t1.join();
		t2.join();
	}
}

In t1
In t2

(t1启动后,持有lock锁,而且suspend()方法不会释放资源,一直持有锁,当t2启动后,无法获得lock锁,t2阻塞;当t1.resume()执行后,t1继续执行,释放lock锁,此时t2获得lock锁,打印In t2,之后t2挂起;与此同时main线程中执行了t2.resume(),这个resume方法没有生效,造成t2永远挂起,并且永远占有lock锁;)

示例代码中,t2线程的resume()方法就在其suspend()方法前执行了,导致t2线程被挂起,程序不会退出,永远被挂起,并且永远占用lock对象的锁;

使用wait()方法和notify()方法模拟挂起和继续执行功能:

public class WaitNotifySimulateSuspendResumeDemo {
	public static Object lock = new Object();
	public static class ChangeObjectThread extends Thread {
		private volatile boolean suspendme = false;
		public void suspendMe() {
			suspendme = true;
		}
		public void resumeMe() {
			suspendme = false;
			synchronized (this) {
				notify();
			}
		}
		@Override
		public void run() {
			while (true) {
				synchronized (this) {
					while (suspendme) {
						try {
							wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
				synchronized (lock) {
					System.out.println("In ChangeObjectThread");
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				Thread.yield();
			}
		}
	}
	public static class ReadObjectThread extends Thread {
		@Override
		public void run() {
			while (true) {
				synchronized (lock) {
					System.out.println("In ReadObjectThread");
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				Thread.yield();
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		ChangeObjectThread t1 = new ChangeObjectThread();
		ReadObjectThread t2 = new ReadObjectThread();
		t1.start();
		t2.start();
		Thread.sleep(1000);
		t1.suspendMe();
		System.out.println("suspend t1 2 seconds.");
		Thread.sleep(2000);
		System.out.println("resume t1");
		t1.resumeMe();
		t1.join();
		t2.join();
	}
}

6、等待线程结束join()和谦让yeild()

public final void join() throws InterruptedException
public final synchronized void join(long millis) throws InterruptedException
public class JoinDemo {
	public volatile static int i = 0;
	public static class IncrementThread extends Thread {
		@Override
		public void run() {
			for (i = 0; i < 10000000; i++)
				;
		}
	}
	public static void main(String[] args) throws InterruptedException {
		IncrementThread it = new IncrementThread();
		it.start();
		it.join();
		System.out.println(i);
	}
}

输出i的值为10000000,即it.join()保证了main线程等待IncrementThread执行完毕了之后,再输出i的值;

public static native void yield();

yield()方法会让出CPU,还会进行CPU资源的争夺,但是是否能够再次被分配时间片就不一定了;

<think>好的,用户现在想了解在Linux环境下C++可以实现的功能和应用场景。之前已经给过详细的回答,现在用户再次提问,需要结合提供的引用资料来优化回答,同时保持结构清晰和真实可靠。 首先,回顾之前的回答,分成了系统级软件开发、嵌入式应用、服务器后端、科学计算与AI四个部分。现在需要参考用户提供的引用内容来补充或调整这些部分。 引用[1]提到了《Linux C与C++一线开发实践》,里面涉及环境搭建、调试、并发编程等,可以在系统工具和开发环境部分补充相关内容。例如,在系统级软件开发中加入包管理器或性能工具的开发,引用[1]中的调试工具如GDB,可以补充到系统工具链开发中。 引用[2]强调C++与Linux结合的优势,如系统级编程、高性能计算,可以进一步强调这些应用场景,并可能提到游戏开发,但根据之前的回答,游戏开发可能不在主要场景中,需要确认是否合适加入。 引用[3]关于问题诊断和调优,可以补充在系统工具开发或服务器后端的高性能服务中,比如性能分析工具的开发,或者优化数据库引擎时使用perf、valgrind等工具。 引用[4]涉及动态库编译,可以在系统级开发或服务器开发中补充动态库的使用,比如在开发分布式存储或网络协议栈时如何利用动态库。 用户的问题集中在功能和应用场景,需要确保每个部分都有具体的例子和引用支持。例如,在系统级软件开发中,可以引用[1]中的调试和并发编程,以及[3]中的诊断工具;在嵌入式部分,引用[1]的部署与发布,如Makefile和持续集成;服务器后端可以结合引用[4]的动态库使用。 同时,用户可能希望了解如何入门或推荐资源,所以最后可以加入推荐的书籍,如引用[1]提到的书籍,并总结学习路径。 需要检查是否有遗漏的应用场景,比如引用[2]提到的游戏开发,但根据之前回答和常见应用,可能不是主要部分,可以忽略或简要提及。确保每个应用场景都有实际案例和引用支持,增强可信度。 最后,组织结构保持清晰,分点说明,使用技术术语但不过于晦涩,并自然融入引用标记。确保问题部分覆盖用户可能关心的进阶内容,如性能优化、设计模式、工具选择等。</think>### Linux环境下C++的功能与应用场景解析 Linux与C++的结合为开发者提供了强大的底层控制能力与高性能计算支持,其应用覆盖从操作系统内核到人工智能的广泛领域。以下是主要功能和应用场景的详细分析: --- #### 一、**系统级软件开发** 1. **操作系统核心组件** - **文件系统开发**:C++可用于优化文件系统性能(如ext4/XFS的日志管理模块),利用RAII特性管理资源[^1]。 - **进程/线程调度器**:通过C++20协程或原子操作实现高效调度策略。 - **设备驱动开发**:基于Linux内核模块(LKM)框架,结合C++面向对象特性封装硬件操作: ```cpp class NetworkDriver { public: void init() { /* 注册PCI设备 */ } ssize_t read() { /* DMA数据传输 */ } }; ``` 内核5.10+版本已支持有限C++特性[^1]。 2. **系统工具链开发** - **包管理器核心**:如dpkg/rpm的依赖解析算法,需高效处理树形依赖关系。 - **性能诊断工具**:通过perf工具扩展开发性能监控模块,结合火焰图分析热点函数[^3]。 - **容器运行时**:实现cgroups资源隔离控制,优化Docker容器调度效率。 --- #### 二、**嵌入式与实时系统** 1. **工业控制与物联网** - **实时控制器**:使用Xenomai实时扩展开发PLC逻辑控制模块,确保微秒级响应。 - **车载系统**:基于ROS2框架实现自动驾驶感知模块,依赖C++模板元编程优化计算路径。 - **物联网网关**:通过Poco库实现MQTT/CoAP协议栈,管理百万级设备连接。 2. **内存优化实践** - 嵌入式场景中常使用内存池技术(如Boost.Pool库)避免碎片化。 - 通过`mlock()`系统调用锁定关键内存页,防止被交换到磁盘[^3]。 --- #### 三、**服务器与网络服务** 1. **高性能后端服务** - **金融交易系统**:基于libevent/libuv实现微秒级订单处理,使用无锁队列(如Folly库)提升并发能力。 - **分布式存储**:开发Ceph对象存储引擎,利用C++17并行算法优化数据分片。 - **数据库优化**:重写MySQL的InnoDB存储引擎索引结构,通过SIMD指令加速查询。 2. **网络协议栈开发** - **5G UPF开发**:实现用户面数据包转发,依赖DPDK加速网络I/O。 - **QUIC协议实现**:基于lsquic库开发低延迟传输层,支持HTTP/3标准。 --- #### 四、**科学计算与人工智能** 1. **数值计算** - **有限元分析**:使用Eigen库求解刚度矩阵方程: $$ \mathbf{Ku} = \mathbf{F} $$ 通过OpenMP并行化矩阵运算。 - **计算流体力学**:扩展OpenFOAM求解器,利用CUDA加速流体模拟。 2. **AI推理优化** - **TensorRT插件开发**:自定义算子支持新型神经网络结构。 - **ONNX运行时优化**:通过LLVM JIT编译加速模型推理。 --- #### 五、**开发工具与编译技术** 1. **动态库开发** - 使用`-fPIC`编译选项生成`.so`动态库,通过`dlopen()`实现运行时加载[^4]。 - 示例:开发加密算法库供多个服务调用。 2. **编译优化** - 通过LTO(链接时优化)提升性能,结合`-O3`和`-march=native`优化指令集。 --- #### 六、**学习路径与资源推荐** 1. **推荐书籍** - 《Linux C与C++一线开发实践》:涵盖环境搭建、调试、并发编程等实战内容[^1]。 - 《Effective Modern C++》:掌握C++11/14/17特性在Linux环境的最佳实践。 2. **关键技能** - 掌握GDB调试核心转储(Core Dump)分析方法。 - 熟练使用Valgrind检测内存泄漏和竞态条件。 --- ### 相关问题 1. 如何通过C++优化Linux内核模块的性能? 2. 在嵌入式Linux中如何平衡C++特性与资源限制? 3. 开发高性能网络服务时如何选择I/O多路复用模型? 4. C++动态库与静态库在Linux部署中有何优劣?[^4] 通过上述方向,开发者可在Linux环境下充分发挥C++的高效性与灵活性,应对从底层硬件操作到云端服务的多样化需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值