一、线程的基本概念

什么是线程:Thread

  • 进程内部的一个执行单元,它是程序中一个单一的顺序控制流程。
  • 线程又被称为轻量级进程(lightweight process)
  • 如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为多线程

通俗来讲,在程序中新建一共线程,就好像在程序中新开辟一条道路

二、创建线程的三种方法

1.继承Thread类

  我们新创建的类可以继承Thread类,并且重写Run方法来实现我们想要的方法,并且通过start()方法来启动这一个线程。

示例如下:

package top.dlkkill.th;

public class MyThread extends Thread{

	private String name;

	public MyThread(String name) {
super();
this.name = name;
}
public MyThread() { }
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<20;i++) {
System.out.println(name+" : "+i);
}
} }
//使用如下方式来启动两个线程
public static void test1() {
MyThread th1=new MyThread("th1");
MyThread th2=new MyThread("th2");
th1.start();
th2.start();
return;
}

  这是创建一共线程最简单的方式,但是有很大的约束,因为在Java中的是单继承的,所以一共类只能继承自另外一个类,所以如果要使用这种方法,就必须使得我们的类要Thread类才可以,这样就使得程序很不灵活,有很大的限制。这样我们就引入了第二种方法。

2.实现Runnable接口(静态代理模式)

1)什么是静态代理模式

代理模式主要包含三个角色,即抽象主题角色(Subject)、委托类角色(被代理角色,Proxied)以及代理类角色(Proxy),如上图所示:

  • 抽象主题角色:可以是接口,也可以是抽象类;
  • 委托类角色:真实主题角色,业务逻辑的具体执行者;
  • 代理类角色:内部含有对真实对象RealSubject的引用,负责对真实主题角色的调用,并在真实主题角色处理前后做预处理和后处理。

引自:https://blog.csdn.net/justloveyou_/article/details/79407248

而静态代理模式是指在程序运行前由程序员提前写好固定的代码(与之相对的是动态代理模式)

代理模式简单说就是讲自己的事物委托给代理人,由代理人去处理事物开始,运行,结束的事情。

静态代理模式的实现要求:

  1. 真实角色
  2. 代理角色(持有对真实角色的引用)
  3. 二者实现相同的接口

静态代理模式的实现过程:

  1. 创建真实角色
  2. 创建代理角色+真实角色引用
  3. 执行任务

假设我们由一个人要结婚(真实角色),委托给婚庆公司(代理角色),抽象主题就是结婚

代码如下:

package top.dlkkill.th;

public class Example {
public static void main(String[] args) {
MarryPeople peo=new MarryPeople();
MarryConpany conp=new MarryConpany(peo);
conp.marry();
} } interface Marry{
public void marry();
}
class MarryPeople implements Marry{
@Override
public void marry() {
// TODO Auto-generated method stub
System.out.println("People Marry");
}
}
class MarryConpany implements Marry{
private MarryPeople peo;
public MarryConpany(MarryPeople peo) {
super();
this.peo = peo;
}
@Override
public void marry() {
// TODO Auto-generated method stub
before();
peo.marry();
after();
}
public void before() {
System.out.println("准备工作");
}
public void after() {
System.out.println("收尾工作");
}
}

2)Runable创建线程

优点:

  1. 避免单继承的局限性
  2. 便于共享资源

实现过程如下:

package top.dlkkill.th;

public class MyThread2 implements Runnable{
private String name;
private boolean flag=true;
private int num=50;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(num>0) {
System.out.println(Thread.currentThread().getName()+"抢到----->"+num--);
}
//System.out.println(name+"------->Stop");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} public MyThread2(String name) {
super();
this.name = name;
}
public MyThread2() {
super();
// TODO Auto-generated constructor stub
}
public static void test2() throws InterruptedException {
MyThread2 myth1=new MyThread2("th1");
MyThread2 myth2=new MyThread2("th2");
Thread th1=new Thread(myth1,"路人甲");
Thread th2=new Thread(myth2,"路人乙");
th1.start();
th2.start();
Thread.sleep(100);
myth1.setFlag(false);
myth2.setFlag(false);
return;
}
}

这里我们假设一共50张票,路人甲和路人乙进行抢票。

我们创建了两个线程,但是都共享50张票的资源,当50张票抢完后,两个线程自动结束。

3.实现Callable<V>接口

这种方法的优点是我们可以抛出我们想要的异常进行异常处理,另外可以得到返回值

但是这种方法的实现过程稍显复杂。

示例如下:

package top.dlkkill.th;

import java.util.concurrent.Callable;

public class MyThread3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
for(int i=0;i<300;i++)
continue;
return 300;
}
public static void test3() throws InterruptedException, ExecutionException {
//创建一个线程
ExecutorService exe=Executors.newFixedThreadPool(1);
MyThread3 th=new MyThread3();
//得到返回值
Future<Integer> restult=exe.submit(th);
int num=restult.get();
System.out.println(num);
//结束线程
exe.shutdownNow();
return;
}
}

三、线程的状态与终止

1.状态

2.线程的终止

线程的终止有两种情况:

  1. 自然终止:线程体正常执行完毕
  2. 外部干涉:
    • 线程类中 定义 线程体使用的标识
    • 线程体使用该标识
    • 提供对外的方法改变该标识
    • 外部根据条件调用该方法即可

实例如下:

package top.dlkkill.th;

public class MyThread2 implements Runnable{
private String name;
private boolean flag=true;
private int num=50;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(flag) {
//System.out.println(Thread.currentThread().getName()+"抢到----->"+num--);
System.out.println(name+"----->run");
}
System.out.println(name+"------->Stop");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} public MyThread2(String name) {
super();
this.name = name;
}
public MyThread2() {
super();
// TODO Auto-generated constructor stub
}
public static void test2() throws InterruptedException {
MyThread2 myth1=new MyThread2("th1");
MyThread2 myth2=new MyThread2("th2");
Thread th1=new Thread(myth1,"路人甲");
Thread th2=new Thread(myth2,"路人乙");
th1.start();
th2.start();
Thread.sleep(100);
//标识改变后,线程结束
myth1.setFlag(false);
myth2.setFlag(false);
return;
} }

Java多线程的创建与简单使用的更多相关文章

  1. Java多线程(1) 创建

    一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下以下这张较为经典的图: Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Threa ...

  2. java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)

    今天开始就来总结一下Java多线程的基础知识点,下面是本篇的主要内容(大部分知识点参考java核心技术卷1): 1.什么是线程以及多线程与进程的区别 2.多线程的创建与启动 3.中断线程和守护线程以及 ...

  3. Java多线程的创建(一)

    方法一:继承Thread类实现 1.创建一个类A,并继承Thread类 2.重写A的run()方法 3.创建A的实例对象b,即创建了线程对象 4.使用b调用start()方法:启动线程(会自动调用ru ...

  4. java多线程之创建线程的4种方式及Future

    Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例.Java可以用四种方式来创建线程: 继承Thread创建线程 实现Runnable接口创建线程 实现callab ...

  5. Java多线程的创建(二)

    前言: 虽然java的API中说创建多线程的方式只有两种(There are two ways to create a new thread of execution),分别是继承Thread类创建和 ...

  6. java多线程-线程创建

    Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: ...

  7. Java多线程-----匿名内部类创建线程

       1.继承Thread类创建线程 package com.practise.createthread; public class AnonymousThread { public static v ...

  8. Java多线程——之一创建线程的四种方法

    1.实现Runnable接口,重载run(),无返回值 package thread; public class ThreadRunnable implements Runnable { public ...

  9. Java多线程之创建线程的三种方式比较

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6560057.html  一:继承Thread类创建线程 1:继承Thread类定义线程子类: 2:重写run( ...

随机推荐

  1. PowerDesigner软件建立新模型。

      打开PowerDesigner软件,选择菜单文件->建立新模型,或者敲击键盘ctrl+N   弹出建立新模型窗口,模型类型选择Object-Oriented Model,图选择Class D ...

  2. centos7最小化安装系统

    https://blog.csdn.net/hellboy0621/article/details/80392273

  3. mysql-8.0.13在windows上的部署

    1 .下载mysql-8.0.13-x64 官方网站:https://dev.mysql.com/downloads/mysql/ 2.解压到G盘 3.准备my.ini文件保存到解压目录 [mysql ...

  4. java中使用springmvc实现下载文件

    下载文件具体实现代码: public class TestDownload{ public HttpServletRequest request; public HttpServletResponse ...

  5. FPC导通阻抗计算

    pc线路板是有导电功能的,那么如何仅适用手工计算出线路的阻值能?那么就需要使用到一个公式: W*R*T=6000 W是指铜箔的宽度单位是密耳mil. T是指铜箔厚度单位是盎司oz. R是指铜箔的电阻单 ...

  6. 运维面试题之k8s

    前言: 到了如今年k8s已经是事实上的容器集群标准了,是时候展现我真正的祖传k8s实力了 吐槽: 我干嘛要知道这些,能用不就行了k8s真香 Kubernetes有哪些特性? Kubernetes是自动 ...

  7. 2019.04.21 python核心特征

    本阶段我们将了解Python是如何管理内存的,学习内存管理让我们掌握python的运行机制: 并且在python中有许多函数式编程的特性,比如闭包,装饰器和生成器,这些都是一些比较难掌握的概念,但面试 ...

  8. jenkins+Gitlab+maven+tomcat实现自动集成、打包、部署

    一.前言 首先出于提高自己技术水平和琢磨能做点什么能提高工作效率,上线工作实在无聊.重复(手动编译.打包,传包,重启),于是就想到了jenkins,jenkins持续集成已经不是什么新鲜的话题,网上文 ...

  9. Log4j 2使用教程一【入门】

    环境 操作系统:win10log4j2版本: 2.11.0 准备 下载jar包 官网:https://logging.apache.org/log4j/2.x/download.html 把jar包放 ...

  10. 【转】LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

    用VS2010编译C++项目时出现这样的错误: LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 方案一:(这个方法比较好,在用qt运行时出现问题也能解决) 复制 C:\Windows\ ...