Java语言内置多线程支持: 一个Java程序实际上是一个JVM进程 JVM用一个主线程来执行main()方法 在main()方法中又可以启动多个线程 1.创建新线程 1.1 方法一:使用Thread创建线程 创建MyThread类: 从Thread派生 覆写run()方法 创建MyThread()实例 调用start()启动线程 class MyThread extends Thread{ public void run(){ System.out.println("子线程"); }…
1.线程锁可以嵌套 在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁 Java的线程锁是可重入的锁.对同一个对象,同一个线程,可以多次获取他的锁,即同一把锁可以嵌套.如以下代码 public void add(int m){ synchronized (lock){ this.value += m; another(m); } } public void addAnother(int m){ synchronized (lock){ this.another += m…
多任务 现代操作系统(windows,MacOS,Linux)都可以执行多任务: 多任务就是同时运行多个任务,例如同时开启钉钉.百度网盘.火狐.谷歌.ps等 操作系统执行多任务就是让多个任务交替执行,例如浏览器执行0.001秒,网盘执行0.001秒,钉钉执行0.001秒.因为任务的数量远远多余CPU的数量,因此任务也是交替执行的 进程.线程 进程(Process):一个任务就是一个进程. 线程(Thread):某些进程内部还需要同时执行多个子任务.例如word打字.拼写检查.打印等 进程和线程的…
多线程是Java实现多任务的基础: Thread ExecutorService ScheduledThreadPool Fork/Join Thread对象代表一个线程:调用Tread.currentThread()获取当前线程. 多任务程序通常需要针对每个任务启动一个新的线程,来处理这个用户的请求,也可以从线程池取出一个空闲的线程来处理. 如何在一个线程内传递状态: 例如我们在一个线程处理过程中,经常需要调用不同的类来处理不同的功能,我们如何在这些方法中能够方便的获取到当前的用户? JDK提…
wait和notify synchronized解决了多线程竞争的问题 我们可以在synchronized块中安全的对一个变量进行修改,但是它没有解决多线程协调的问题. 例如设计一个TaskQueue,预期效果:线程1通过addTask()不断往队列中添加任务,而线程2可以调用getTask()从队列中获取任务 class TaskQueue{ Queue<String> queue = new LinkedList<>(); public synchronized void ad…
1.中断线程: 如果线程需要执行一个长时间任务,就可能需要中断线程.场景:从网络上下载一个100M的文件,用户在下载过程中中断下载任务的执行. 中断线程就是其他线程给该线程发一个信号,该线程收到信号后结束执行run()方法 1.1中断线程 需要检测isInterrupted()标志,其他线程通过调用interrupt()方法中断该线程 class HelloThread extends Thread{ public void run(){ while(!isInterrupted()){ Sys…
1线程的状态 线程终止的的原因: run()或call()方法执行完成,线程正常结束 线程抛出一个未捕获的Exception或Error 直接调用该线程的stop()方法来结束该线程--该方法容易导致死锁,通常不推荐使用 1.1对已经死亡的线程调用start()方法使他重新启动,会引发IllegalThreadStateException class MyThread extends Thread{ public void run(){ System.out.println("子线程"…
Atomic java.util.concurrent.atomic提供了一组原子类型操作: 如AtomicInteger提供了 int addAndGet(int delta) int incrementAndGet() int get() int compareAndGet() Atomic类可以实现: 无锁(lock-free)实现的线程安全(thread-safe)访问 原理:CAS(Compare and Set)如果AtomicInteger实例的值是prev,就替换为next,返回…
Concurrent 用ReentrantLock+Condition实现Blocking Queue. Blocking Queue:当一个线程调用getTask()时,该方法内部可能让给线程进入等待状态,直到条件满足.线程唤醒以后,getTask()才会返回,而java.util.concurrent提供了线程安全的Blocking集合,如ArrayBlockingQueue. class TaskQueue{ final Queue<String> queue = new LinkedL…
Java语言内置多线程支持: 创建线程需要操作系统资源(线程资源,栈空间) 频繁创建和销毁线程需要消耗大量时间 如果可以复用一个线程 线程池: 线程池维护若干个线程,处于等待状态 如果有新任务,就分配一个空闲线程执行 如果所有线程都处于忙碌状态,新任务放入队列等待 ExecutorService JDK提供了ExecutorService接口表示线程池: ExecutorService executor = Executors.newFixedThreadPool(4); //固定大小的线程池…
使用Future可以获得异步执行结果 Future<String> future = executor.submit(task); String result = future.get(); 但是当我们使用get()获得异步执行结果的时候,这个方法可能会阻塞.我们通过while循环反复调用isDone()来判断异步结果是否已经完成. while(!future.isDone()){ Thread.sleep(1); } String result = future.get() 所以使用Futu…
Condition实现等待和唤醒线程 java.util.locks.ReentrantLock用于替代synchronized加锁 synchronized可以使用wait和notify实现在条件不满足时的等待,条件满足时的唤醒. class TaskQueue{ final Lock lock = new ReentrantLock() final Condition notEmpty = lock.newCondition(); } 使用Condition对象可以通过await和signa…
ReentrantLock保证单一线程执行 ReentrantLock保证了只有一个线程可以执行临界区代码: 临界区代码:任何时候只有1个线程可以执行的代码块. 临界区指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性.当有线程进入临界区段时,其他线程或是进程必须等待,有一些同步的机制必须在临界区段的进入点与离开点实现,以确保这些共用资源是被互斥获得使用,例如:semaphore.只能被单一线程访问的设备,例如:打印机. public…
1.Java使用synchronized对一个方法进行加锁 class Counter{ int count = 0; public synchronized void add(int n){ count += n; } public synchronized void dec(int n){ count -= n; } public int get(){//读取一个int类型是原子操作,不需要同步 return count; } } class AddThread extends Thread…
1.线程安全问题 多个线程同时运行,线程调度由操作系统决定,程序本身无法决定 如果多个线程同时读写共享变量,就可能出现问题 class AddThread extends Thread{ public void run(){ for(int i=0;i<Main.LOOP;i++){ Main.count += 1; } } } class DecThread extends Thread{ public void run(){ for(int i=0;i<Main.LOOP;i++){ Ma…
线程同步: 是因为多线程读写竞争资源需要同步 Java语言提供了synchronized/wait/notify来实现同步 编写多线程同步很困难 所以Java提供了java.util.concurrent包: 更高级的同步功能 简化多线程程序的编写 JDK>= 1.5 java.util.locks.ReentrantLock用于替代synchronized加锁 synchronized是Java语言提供的,不需考虑异常 ReentrantLock是普通的Java类,要用try...finall…
线程池可以高效执行大量小任务: Fork/Join线程池可以执行一种特殊的任务: 把一个大任务拆成多个小任务并行执行 Fork/Join是在JDK 1.7引入的 示例:计算一个大数组的和 Fork/Join就是把一个大人物不断的拆成小任务,执行并行计算的一种模式. class SumTask extends RecursiveTask<Long> { protected Long compute(){ //把一个大任务分拆成2个子任务 SumTask subtask1 = new Sumtas…
JDK提供了ExecutorService接口表示线程池,可以通过submit提交一个任务. ExecutorService executor = Executors.newFixedThreadPool(4); executor.submit(task); 但这里的task有个问题,因为继承制Runnable,如果希望返回一个结果,只能用Result来表示,这样主线程获取结果,就很不方便. class Task implements Runnable{ public String result…
TCP多线程编程 一个ServerSocket可以和多个客户端同时建立连接,所以一个Server可以同时与多个客户端建立好的Socket进行双向通信. 因此服务器端,当我们打开一个Socket以后,通常使用一个无限for循环,在这个for循环内部,每次调用accept方法,返回一个与远程客户新建的Socket连接,紧接着启动一个新的线程,来处理这个连接. ServerSocket ss = new ServerSocket(port); for( ; ; ){ Socket sock = ss.…
1.JDK提供的InputStream分为两类: 直接提供数据的InputStream * FileInputStream:从文件读取 * ServletInputStream:从HTTP请求读取数据 * Socket.getInputStream():从TCP连接读取数据 提供额外附加功能的FilterInputStream * 如果要给FileInputStream添加缓冲功能: BufferedFileInputStream extends FileInputStream * 如果要给Fi…
Semaphore负责协调线程,可以限制对某一资源访问的线程数量 这里对SemaphoreSlim类的用法做一个简单的例子: namespace WpfApplication6 { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { static SemaphoreSlim semLim = new SemaphoreSlim(3); //…
字符串操作过程中,每次用 + 拼接字符串,有以下问题: 每次循环都会创建新的对象 绝大部分都是临时对象.浪费内存 影响GC效率 String s = ""; for(int i=0;i<1000;i++){ s = s +String.valueOf(i); } System.out.println(s); 为了解决这个问题,Java提供了StringBuilder类,可以高效的拼接字符串 1.StringBuffer类 StringBuilder是可变对象 StringBuil…
一.NSOperation的基本概念1.简介NSOperation的作用配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤先将需要执行的操作封装到一个NSOperation对象中然后将NSOperation对象添加到NSOperationQueue中系统会自动将NSOperationQueue中的NSOperation取出来将取出的NSOperation封装的操作放到一条新线程中执行 2…
1.进程和线程       进程,是一个正在运行的程序实体,windows下常见的就是xxx.exe,在任务管理器中可以看见很多个进程.它是线程的容器. 线程,是进程中的一个执行流.在单线程编程中,我们的程序只有一个执行流:主线程的main方法.流,表明执行的过程是有顺序的,如main函数中的语句需要一条一条的按顺序执行,第一条语句没执行完,就不能去执行第二条语句. 可见,单线程编程是有限制的,那就是我们的语句只能串行执行,不可能发生某些语句同时执行的现象.有时我们希望某些代码并行执行,就好比我…
转自: http://www.cnblogs.com/lgxqf/archive/2009/02/10/1387480.html 在 Win32 API 中,创建线程的基本函数是 CreateThread,而 _beginthread(ex) 是C++ 运行库的函数.为什么要有两个呢?因为C++ 运行库里面有一些函数使用了全局量,如果使用 CreateThread 的情况下使用这些C++ 运行库的函数,就会出现不安全的问题.而 _beginthreadex 为这些全局变量做了处理,使得每个线程都…
1.进程与线程的概念 现在几乎所有操作系统都支持多任务,通常一个任务就是一个程序,一个运行中的程序就是一个进程.当一个程序行时,其内部也可能在执行多个任务,进程内每一个任务的执行流,就是一个线程. 所以线程也被称作轻量级进程. 总而言之,线程是进程的组成部分,可以独立.并发的执行任务. 2.线程的创建和启动 Java中有两种方式来创建和启动线程. 2.1继承Thread类创建和启动线程 通过继承Thread类创建并启动多线程的步骤如下: 1.创建Thread的子类,并重写run方法.run方法中…
Thread实现多线程: public class Thread2 extends Thread{ public  int i; public void run(){ for(; i < 100 ;i++) { System.out.println(getName() + " " + i); } } public static void main(String[] args){ for (int j = 0; j < 100; j++) { System.out.print…
Spark提交程序报错,无法创建新的线程 原因是因为这台公用机器上跑的进程太多了,需要修改Linux参数,允许用户最大进程数 查看允许用户最大进程数配置 ulimit -a 修改允许用户最大进程数配置 vim /etc/profile 在文件后面追加一句,并使配置立即生效,设置太大也不好,Java内存不够用[囧] ulimit -u source /etc/profile…
项目中使用了spring-data-redis 实现消息订阅功能,原来的配置是这样子: <redis:listener-container connection-factory="jedisConnectionFactory"> <redis:listener ref="listener" serializer="jdkSerializer" method="onReceive" topic="my…
环境介绍 JDK版本:1.8 开发架构:spring boot 2.x 日志:slf4j 实现步骤 Runnable接口中只有一个run()方法,它是非Thread类子类的类提供的一种激活方式.一个类实现Runnable接口后,并不代表该类是一个“线程”类,不能直接运行,必须通过Thread实例才能创建并运行线程. 通过Runnable接口创建线程的步骤如下: 1.定义实现Runnable接口的类,并实现该类中的run()方法. 2.建立一个Thread对象,并将实现的Runnable接口的类的…