并发,就是用多个执行器(线程)来完成一个任务(大任务)来处理业务(提高效率)的方法。而在这个过程中,会涉及到一些问题,所以学的就是解决这些问题的方法。

线程的基本操作:

  1、创建线程:只需要new一个线程对象即可:Thread myThread=new Thread()。然后 myThread.start() 即可开启线程。那么问题来了,这个线程到底要做些什么呢,所以,Thread有一个run() 方法,方法体则是线程要做的事情。而默认情况下,run()方法什么不做,所以我们需要重写run(),把你要做的事情填进去。

 public static void main(String[] args) {
Thread t1=new Thread(){
@Override
public void run() {
System.out.println("hello i am t1");
}
};
t1.start();
}

  上面使用匿名内部类的方式重写了run方法。

  因为Java是单继承的,有时候继承也是一种稀缺的资源,所以可以用Runable接口来实现:

public interface Runnable{
public abstract void run();
}

  Runnable接口就只有一个run方法。

  Thread类还有一个重要的构造方法:public Thread (Runnable target) ,所以,可以通过实现了Runnable接口的类的实力来创建线程,同时,Runnable是一个函数式接口,所以还可以使用Lambda表达式:

public static void main(String[] args) {
Thread t1=new Thread(()-> System.out.println("hello i am t1"));
t1.start();
}

  2、终止线程:Thread.stop() 可以终止线程,但是它是一个废弃的方法,因为它太过暴力,即使线程正在执行中,也会直接终止,并释放锁。

  3、线程中断:线程中断不会使线程立即退出,而是给线程发送一个通知,告诉目标线程:有人希望你退出啦!至于目标线程如何处理,还是又目标线程自己决定。

        有关线程中断的三个方法:Thread.interrupt() 中断线程。Thread.isInterruputed() 判断是否被中断了。 Thread.interrupted() 判读是否被中断,并且清除中断状态。

 public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(){
@Override
public void run() {
while (true)
System.out.println("t1 is running.");
}
};
t.start();
Thread.sleep(1000);
t.interrupt();
}

    上面代码中,对线程t进行了中断,但并没有作出中断后的操作,所以是没有效果的。改进:

public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(){
@Override
public void run() {
while (true){
if (Thread.currentThread().isInterrupted())
break;
System.out.println("t1 is running.");
}
}
};
t.start();
Thread.sleep(1000);
t.interrupt();
}

  4、等待(wait)和通知(notify):为了支持多线程之间的协作,JDK提供了wait()和notify(),这两个方法并不在Thread类中,而是在Object中,也就是说,任何对象都可以调用这两个方法。

    当线程A 调用了obj.wait()方法后,线程A就会停止执行,转为等待状态。等待的状态要等到其他线程调用obj.notify()方法为止。

    当某个线程调用了object.wait()方法后,该线程就会进去object对象的等待队列。这个等待队列中,可能有多个线程。当调用 object.notify()时,会随机在队列中唤醒一个线程。而调用object.notifyAll()时,会唤醒所有线程。

    注意:wait()和notify()都必须在synchronized语句中,必须先获得目标对象的监听器,才能调用这两个方法。调用wait后,会释放监听器。

  5、挂起(suspend)和继续执行(resume):suspend可以停止线程执行,直到resume。但suspend停止时,不会释放资源,所以不推荐使用。

  6、等待线程结束(join)和谦让(yeild):线程之间协作时,有时会有先后关系,也就是B线程等到A线程执行完了,再执行。

volatile:

  当用volatile关键字申明变量时,就等于告诉虚拟机,这个变量极有可能会被某些线程修改,虚拟机就会做一些操作,来确保这个变量背修改后,应用程序范围内的所有线程都能看到这个改动。用volatile申明的变量可以保证有序性和可见性,但无法保证原子性。

守护线程:

  守护线程是一种特殊的线程,它是系统的守护者,在后台完成一些系统性的服务,比如垃圾回收线程。与之对应的是用户线程。当一个Java应用只有守护线程时,Java虚拟机就会自然退出。setDaemon()可以将线程设为守护线程。

public class test {
public static class DaemonThread extends Thread{
@Override
public void run() {
while (true){
System.out.println("i am alive");
}
}
} public static void main(String[] args) throws InterruptedException {
Thread thread=new DaemonThread();
thread.setDaemon(true);
thread.start();
Thread.sleep(2000);
}
}

  将thread设置为守护线程,所以在主线程休眠2s后,用户线程全部结束,整个程序也就结束了。

线程优先级:

  优先级高的线程在竞争资源时,会更有优势。但是这只是概率问题,运气不好的话,高优先级的线程也可能抢占资源失败。setPriority()来设置线程优先级。

public class test {
final static Object obj=new Object();
public static class Low extends Thread{
static int i=0;
@Override
public void run() {
while (true){
synchronized (obj){
i++;
if (i>100000){
System.out.println("low complete。");
break;
}
}
}
}
}
public static class High extends Thread{
static int i;
@Override
public void run() {
while (true){
synchronized (obj){
i++;
if (i>150000){
System.out.println("high complete.");
break;
}
}
}
}
} public static void main(String[] args) {
Thread low=new Low();
Thread high=new High();
low.setPriority(Thread.MIN_PRIORITY);
high.setPriority(Thread.MAX_PRIORITY);
low.start();
high.start();
} }

  上述代码中,即使high要多加50000次,但是因为优先级高,会更先执行完。

Synchronized

  关键字synchronized的作用是实现线程间的同步。它的工作是对同步的代码加锁,使得每一次只有一个线程进入同步快,从而保证线程间的安全性。

  用法:可以给指定对象加锁(上面事例中),也可以作用于实例方法:

public class test implements Runnable {
static test t=new test();
static int i=0;
public synchronized void add(){
i++;
} @Override
public void run() {
for (int k=0;k<100000;k++)
add();
} public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
t2.start();
t1.join();t2.join();
System.out.println(i);
}
}

Java并行程序基础。的更多相关文章

  1. Java并发程序设计(二)Java并行程序基础

    Java并行程序基础 一.线程的生命周期 其中blocked和waiting的区别: 作者:赵老师链接:https://www.zhihu.com/question/27654579/answer/1 ...

  2. JAVA并行程序基础

    JAVA并行程序基础 一.有关线程你必须知道的事 进程与线程 在等待面向线程设计的计算机结构中,进程是线程的容器.我们都知道,程序是对于指令.数据及其组织形式的描述,而进程是程序的实体. 线程是轻量级 ...

  3. JAVA并行程序基础二

    JAVA并行程序基础二 线程组 当一个系统中,如果线程较多并且功能分配比较明确,可以将相同功能的线程放入同一个线程组里. activeCount()可获得活动线程的总数,由于线程是动态的只能获取一个估 ...

  4. JAVA并行程序基础一

    JAVA并行程序基础一 线程的状态 初始线程:线程的基本操作 1. 新建线程 新建线程只需要使用new关键字创建一个线程对象,并且用start() ,线程start()之后会执行run()方法 不要直 ...

  5. 第2章 Java并行程序基础(三)

    2.8 程序中的幽灵:隐蔽的错误 2.8.1 无提示的错误案例 以求两个整数的平均值为例.请看下面代码: int v1 = 1073741827; int v2 = 1431655768; Syste ...

  6. 第2章 Java并行程序基础(二)

    2.3 volatile 与 Java 内存模型(JMM) volatile对于保证操作的原子性是由非常大的帮助的(可见性).但是需要注意的是,volatile并不能代替锁,它也无法保证一些复合操作的 ...

  7. 第2章 Java并行程序基础(一)

    2.1 有关线程你必须知道的事 进程是系统进行资源分配和调度的基本单位,是程序的基本执行实体. 线程就是轻量级进程,是程序执行的最小单位. 线程的生命周期,如图2.3所示. 线程的所有状态都在Thre ...

  8. 到头来还是逃不开Java - Java13程序基础

    java程序基础 没有特殊说明,我的所有学习笔记都是从廖老师那里摘抄过来的,侵删 引言 兜兜转转到了大四,学过了C,C++,C#,Java,Python,学一门丢一门,到了最后还是要把Java捡起来. ...

  9. Spring MVC + Spring + Mybitis开发Java Web程序基础

    Spring MVC + Spring + Mybitis是除了SSH外的另外一种常见的web框架组合. Java web开发和普通的Java应用程序开发是不太一样的,下面是一个Java web开发在 ...

随机推荐

  1. [Go] 利用channel实现简单的工作池

    先启动固定数量的goroutine,每个goroutine都在从channel中获取数据,如果这个channel为空,就阻塞等待在那里channel中传递一个Car类型,这个类型主要负责具体做的任务也 ...

  2. appium---元素定位方法

    在我们做自动化测试的过程中,最基本的就是要会元素定位,也是自动化中的灵魂所在,如果一个自动化测试工程师说不会定位元素定位,那么肯定也不会做自动化了. 如何查看元素 小伙伴们都知道如果是web端可以通过 ...

  3. 多线程状态与优先级、线程同步与Monitor类、死锁

    一.线程状态 二.线程优先级 三.初步尝试多线程 class Program { static void Main(string[] args) { while (true) { MessagePri ...

  4. 浅谈this指向问题

    链接地址:https://www.jianshu.com/p/34572435b5d0

  5. 2019年最新50道java基础部分面试题

    [软帝学院]1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法. 1.一个".j ...

  6. 文件名工具类 MoFileNameUtil

    文件名工具类 MoFileNameUtil MoFileNameUtil public class MoFileNameUtil { //不包含点号 public static String getF ...

  7. 【声明式事务】Spring声明式事务实现(三)

    以MyBatis为例. 一.基于注解的声明式事务配置 1. 添加tx名字空间 xmlns:tx="http://www.springframework.org/schema/tx" ...

  8. 选择排序法(C语言)

    基本思路 在每一次的排序中选出最小(或最大)的数,将其放在数组最前端,然后在后面的数中重复此步骤,最终达到排序的目的. 算法描述 将存于数组首位数与后面的数依次比较,将其中的较小的数放到数组放到数组首 ...

  9. js json字符串与json对象互相转换(最全)

      1.json字符串转json对象 使用场景:通常在取json字符串里具体的值时,会用到. var jsonString = '{"name":"Marydon&quo ...

  10. Emgucv 4 下载、安装、配置

    1.下载.安装 过程可查看之前Emgucv 3的说明:https://www.cnblogs.com/doget/p/7776377.html 安装完成后,安装目录下会生成如下文件及文件夹: 2.配置 ...