Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java-多线程

Java-多线程

作者头像
WuShF
发布于 2023-07-08 07:50:38
发布于 2023-07-08 07:50:38
22300
代码可运行
举报
文章被收录于专栏:笔记分享笔记分享
运行总次数:0
代码可运行

进程与线程

程序>进程>线程

程序是一段静止的代码,只有真正运行时的程序,才被称为进程。一个程序运行至少有一个进程 从操作系统底层来说,进程只是一个概念,真正执行的是线程。

进程是操作系统资源分配的基本单位,而线程是CPU的基本调度单位。 线程是进程中的一个执行路径,共享同一个进程内存空间。 线程之间可以自由切换,并发执行,一个进程最少有一个一个线程。线程是CPU的基本调度单位。 进程之间不能共享数据段地址,但同进程的线程之间可以。


单核CPU在任何时间点上,只能运行一个进程:宏观并行,微观串行。 进程由多个线程组成,彼此之间完成不同的工作,交替执行,被称为多线程。 对于一个Java程序,至少有两个线程。

  • main方法,也称主线程。
  • 垃圾回收器GC,在JVM启动时自动启动。

线程的组成

任何一个线程都具有的基本组成部分: CPU时间片:操作系统会为每个线程分配执行时间。

  • 不是我们去控制CPU,而是CPU根据操作系统为我们分配执行时间。

运行数据:

  • 堆空间:存储线程需使用的对象,多个线程可以共享堆中的对象。
  • 栈空间:存储线程需使用的局部变量,每个线程都拥有独立的栈。

线程的两种实现方式

并行与并发

并行:多个任务同时执行(多个CPU)。 并发:多个任务同时请求运行,而处理器一次只能接受一个任务,就会把两个任务安排轮流执行,由于CPU时间片运行时间较短,就会感觉两个任务在同时执行。

创建线程一共有两种方式,分别是:继承Thread类和实现Runable方法。 启动线程是通过调用start()方法,表示线程已经准备就绪,等待CPU分配时间片。一旦CPU分配了时间片,线程就会自动运行。 start()方法不是启动线程,而是说这个线程已经准备就绪,等待CPU调度。

继承Thread类

  1. 继承Thread
  2. 覆盖run()方法
  3. 创建子类对象
  4. 调用start()方法
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        //创建子类对象
        MyThread myThread = new MyThread();
        //调用start()方法
        myThread.start();
    }
}

//继承Thread类
class MyThread extends Thread {
    @Override
    //重写run方法
    public void run() {
        for (int i = 0; i < 100; i++)
            System.out.println(i);
    }
}

实现Runable方法

  1. 实现Runable接口类
  2. 覆盖run()方法
  3. 创建实现类对象
  4. 创建线程对象
  5. 调用start()方法
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        //创建实现类对象
        MyRunable myRunable = new MyRunable();
        //创建线程对象
        Thread thread = new Thread(myRunable);
        //调用start方法
        thread.start();
    }
}

//实现Runable接口类
class MyRunable implements Runnable {
    @Override
    //重写run方法
    public void run() {
        for (int i = 0; i < 100; i++)
            System.out.println(i);
    }
}

如果使用类的方式来创建线程,代码看起来更加方便简单。 如果使用接口的方式来创建线程,要先编写任务,然后将任务交给线程类才能启动。要多一个步骤,看起来更加麻烦。 但更常用的还是接口的方式,因为接口更加灵活,可以继承多个。 如果使用类的方法,那么将无法继承其他的类。而如果使用接口,那么仍然可以继承其他的类,不会被因承继Thread类限制住。

接口回调

我们通过线程往外返回结果的时候,直接返回是没有办法返回数据的。可以通过接口调用的方法传递数据。 也就是在线程内部定义一个接口,谁需要返回数据,谁里面就定义一个接口,来做数据的返回。


模拟一个系统登陆功能,使用随机验证码来防止暴力破解方式进行不断的登陆尝试。 实现要求: 利用线程实现生成4位验证码,要求验证码由数字、字母组成,生成后显示出来。然后用户输入验证码,判断验证码是否正确。


代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.Random;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        ValidateCodeThread validateCodeThread = new ValidateCodeThread();
        ValidateCodeThread.OnResultListener onResultListener = new ValidateCodeThread.OnResultListener() {
            @Override
            public void onResult(String result) {
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入验证码:");
                String userCode = scanner.nextLine();
                System.out.println(result.equals(userCode));
            }
        };
        validateCodeThread.setOnResultListener(onResultListener);
        Thread thread = new Thread(validateCodeThread);
        thread.start();

    }
}

//创建验证码的线程任务
class ValidateCodeThread implements Runnable {
    private String codes = "23456789abcdefghjkmnpqrstuvwxyz";
    private OnResultListener onResultListener;

    public void setOnResultListener(OnResultListener onResultListener) {
        this.onResultListener = onResultListener;
    }

    Random r = new Random();
    int num = 4;
    StringBuffer sb = new StringBuffer(4);

    @Override
    public void run() {
        for (int i = 0; i < num; i++) {
            int index = r.nextInt(codes.length());
            sb.append(codes.charAt(index));
        }
        System.out.println("生成的验证码是" + sb);
        if (onResultListener != null) {
            onResultListener.onResult(sb.toString());
        }
    }

    interface OnResultListener {
        public void onResult(String result);
    }
}

线程休眠

public static native void sleep(long millis) throws InterruptedException; 只要使用native修饰的方法都是本地方法。此方法不是由Java实现,而是由底层的C/C++实现,然后回调到sleep方法。

数列中随机生成不重复数

需求:从1~100中随机产生10个不重复的数。


普通的算法逻辑:

  1. 随机生成第一个数,放到结果数组的第0个位置。
  2. 随机生成第二个数,与结果数组中已存在的数比较,如果相同,重新生成,直到不同,放到结果数组中。
  3. 重复第2步,直到生成10个数结束。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.Arrays;
import java.util.Random;

public class Main {
    public static void main(String[] args) {
        int[] ints = new int[100];
        for (int i = 0; i < 100; i++) {
            ints[i] = i + 1;
        }
        int[] result = new int[10];
        boolean flag = true;
        Random random = new Random();
        for (int i = 0; i < result.length; i++) {
            flag = true;
            while (flag) {
                boolean b = true;
                int index = random.nextInt(ints.length);
                for (int j = 0; j < i; j++) {
                    if (ints[index] == result[j]) {
                        b = false;
                        break;
                    }
                }
                if (b) {
                    result[i] = ints[index];
                    flag = false;
                }
            }
        }
        System.out.println(Arrays.toString(result));
    }
}

优化后的算法逻辑

我们可以将随机的元素与数组末尾的元素进行交换,下次取值的时候通过数组元素个数减1的方式来随机产生一个数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.Arrays;
import java.util.Random;

public class Main {
    public static void main(String[] args) {
        int[] ints = new int[100];
        for (int i = 0; i < ints.length; i++) {
            ints[i] = i + 1;
        }
        int[] result = new int[10];
        Random random = new Random();
        for (int i = 0; i < result.length; i++) {
            int index = random.nextInt(ints.length - i);
            result[i] = ints[index];
            ints[ints.length - 1 - i] = ints[index] + ints[ints.length - 1 - i];
            ints[index] = ints[ints.length - 1 - i] - ints[index];
            ints[ints.length - 1 - i] = ints[ints.length - 1 - i] - ints[index];
        }
        System.out.println(Arrays.toString(result));
    }
}

添加休眠功能

使用Thread.sleep(long millis)方法实现线程休眠。 使用Thread.sleep(long millis)可能返回中断,需要用try-catch语句包裹。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.Random;

public class Main {
    public static void main(String[] args) {
        GenRandomNums genRandomNums = new GenRandomNums();
        Thread thread = new Thread(genRandomNums);
        thread.start();
    }
}

class GenRandomNums implements Runnable {
    @Override
    public void run() {
        int[] ints = new int[100];
        for (int i = 0; i < ints.length; i++) {
            ints[i] = i + 1;
        }
        int[] result = new int[10];
        Random random = new Random();
        for (int i = 0; i < result.length; i++) {
            int index = random.nextInt(ints.length - i);
            result[i] = ints[index];
            ints[ints.length - 1 - i] = ints[index] + ints[ints.length - 1 - i];
            ints[index] = ints[ints.length - 1 - i] - ints[index];
            ints[ints.length - 1 - i] = ints[ints.length - 1 - i] - ints[index];
        }
        for (int i = 0; i < result.length; i++) {
            System.out.print(result[i] + " ");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

自定义标记中断线程

中断线程可以利用方法对象.interrupt();为线程打上中断标记,在线程内使用Thread.interrupted()方法判断是否中断,该方法的返回值为Boolean类型,根据返回值判断接下来的操作。 Java提供的中断方法并不会强行结束线程,只是为线程打上中断标记。如何中断交由线程自己决定。 也可以在类内添加标记flag,通过在类外手动为flag赋值,根据不同的值进行不同的操作,实现中断功能。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class GenRandomNums implements Runnable {
    @Override
    public void run() {
        Boolean flag = true;
        int[] ints = new int[100];
        for (int i = 0; i < ints.length; i++) {
            ints[i] = i + 1;
        }
        int[] result = new int[10];
        Random random = new Random();
        for (int i = 0; i < result.length && flag; i++) {
            int index = random.nextInt(ints.length - i);
            result[i] = ints[index];
            ints[ints.length - 1 - i] = ints[index] + ints[ints.length - 1 - i];
            ints[index] = ints[ints.length - 1 - i] - ints[index];
            ints[ints.length - 1 - i] = ints[ints.length - 1 - i] - ints[index];
        }
        for (int i = 0; i < result.length && flag; i++) {
            System.out.print(result[i] + " ");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

获取线程名称

Thread.currentThread().getName()会返回当前线程的名称。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.Random;

public class Main {
    public static void main(String[] args) {
        ThraedName thraedName = new ThraedName();
        Thread thread = new Thread(thraedName);
        thread.start();
        //main:main
        System.out.println("main:" + Thread.currentThread().getName());
        //thread:Thread-0
        System.out.println("thread:" + thread.getName());
    }
}

class ThraedName implements Runnable {
    @Override
    public void run() {
        //GenRandomNums:Thread-0
        System.out.println("GenRandomNums:" + Thread.currentThread().getName());
    }
}

线程同步与安全性

线程安全问题

多个线程操作同一个数据出现的数据不统一问题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Main {
    public static void main(String[] args) {
        TicketThread ticketThread = new TicketThread();
        Thread t1 = new Thread(ticketThread);
        Thread t2 = new Thread(ticketThread);
        Thread t3 = new Thread(ticketThread);
        Thread t4 = new Thread(ticketThread);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class TicketThread implements Runnable {
    private int num = 10;

    @Override
    public void run() {
        while (num != 0) {
            System.out.println(Thread.currentThread().getName() + "-当前:" + num-- + "剩余" + num);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程同步

只有拥有对象互斥锁标记的线程,才能进入该对象加锁的同步代码块。 线程退出同步代码块时,会释放相应的互斥锁标记。 需要注意的是,sleep()方法不会释放锁。

synchronized()同步代码块

synchronized(要同步的对象){要同步的操作} 括号内"要同步的对象"只是一个标记作用,没有其他含义。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//同步代码块
synchronized (this) {
    while (num != 0) {
        System.out.println(Thread.currentThread().getName() + "-当前:" + num-- + "剩余" + num);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

同步方法

同步的对象是当前对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//同步方法,同步的对象是当前对象
private synchronized void ticket() {
    while (num != 0) {
        System.out.println(Thread.currentThread().getName() + "-当前:" + num-- + "剩余" + num);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Lock.lock();锁同步

更加灵活,可以自定义同步区域。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private Lock lock = new ReentrantLock();

@Override
public void run() {
    if (lock.tryLock()) {
        lock.lock();
    }
    while (num != 0) {
        System.out.println(Thread.currentThread().getName() + "-当前:" + num-- + "剩余" + num);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

同步规则

只有在调用包含同步代码块的方法,或者同步方法时,才需要对象的锁标记。 如调用不包含同步代码块的方法,或普通方法时,则不需要锁标记,可直接调用。 Java中线程安全的类包括:StringBuffer类、集合类等,这些类的公开方法均为synchonized修饰的同步方法。

如果需求中存在多线程同时访问,那么建议使用StringBuffer类。如果只有一个线程,那么建议使用StringBuilder类。 同步会增加性能的消耗,但在多线程的时候又不得不使用同步,否则会出现数据错乱、数据不安全的问题。通常是用确保数据安全换取性能的牺牲。性能和安全是相辅相成的。

死锁问题

如果线程进行同步,那么他就会上锁,此时如果其他线程如果要执行,就要在门口等待,就会出现死锁:想要获取这个锁,但一直获取不到。

线程池

线程是宝贵的内存资源,单个线程占用约1M左右的内存空间,过多分配容易造成内存溢出。 频繁的创建和销毁线程会增加虚拟机回收频率造成程序性能下降。

线程池

线程容器,可设定线程分配的数量上限。将预先创建的线程对象存入池中,并重用线程池中的线程对象。避免频繁的创建和销毁。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        //创建三个线程的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        //提交到任务队列
        executorService.submit(new TicketThread());
        executorService.submit(new TicketThread());
        executorService.submit(new TicketThread());
        executorService.submit(new TicketThread());
    }
}

class TicketThread implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

多线程应用

生产者与消费者的协作案例

this.wait();//线程进入等待状态,把CPU时间片让出去,释放监视器所有权(对象锁),等待其他方法使用notify()方法唤醒。 Thread.sleep();///线程进入休眠状态,把CPU时间片让出去,但不会释放对象锁 this.notify();//按优先级唤醒等待中的一个线程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        Food food = new Food();
        Producter p = new Producter(food);
        Customers c = new Customers(food);
        Thread thread1 = new Thread(p);
        Thread thread2 = new Thread(c);
        thread2.start();
        thread1.start();
    }
}

class Customers implements Runnable {
    private Food food;

    public Customers(Food food) {
        this.food = food;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            food.get();
        }
    }
}

class Producter implements Runnable {
    private Food food;

    public Producter(Food food) {
        this.food = food;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if (i % 2 == 0) {
                food.set("牛肉拉面", "味道美极了");
            } else {
                food.set("韭菜炒鸡蛋", "大补啊");
            }
        }
    }
}

class Food {
    private String name;
    private String desc;
    Boolean flag = true;//true表示可以生产,false表示可以消费

    //生产食物
    public synchronized void set(String name, String desc) {
        //如果能消费不能生产
        if (!flag) {
            try {
                //线程进入等待状态,释放监视器所有权(对象锁)
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.name = name;
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.desc = desc;
        //生产完成,可以消费
        flag = false;
        //按优先级唤醒等待中的一个线程
        this.notify();
    }

    //获取食物
    public synchronized void get() {
        //如果能生产不能消费
        if (flag) {
            try {
                //线程进入等待状态,释放监视器所有权(对象锁)
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + "->" + desc);
        //消费完成,可以生产
        flag = true;
        //按优先级唤醒等待中的一个线程
        this.notify();
    }

}

线程隔离

ThreadLocal提供一个线程Thread局部变量,访问到某个变量的每一个线程都拥有自己的局部变量。可以在多线程环境下保证成员变量的安全。 ThreadLocal并不是用来解决多线程环境下共享变量的问题。而是用来提供线程内部共享变量的问题。

对比synchronized

ThreadLocal是采用空间换时间的方式,为每一个线程都提供一份变量的副本,实现同时访问、互不干扰,在多线程当中让每个线程之间的数据相互隔离。 synchronized同步机制采用的是时间换空间的方式,只提供一份,让线程排队访问,在多线程之间访问资源同步。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.lang.Thread;

public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);
        thread1.start();
        thread2.start();
    }
}

class MyThread implements Runnable {
    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            threadLocal.set(i);
            System.out.println(Thread.currentThread().getName() + "threadLocal.get()=" + threadLocal.get());
        }
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-07-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
手把手教你使用CNN进行交通标志识别(已开源)
在本文中,使用Python编程语言和库Keras和OpenCV建立CNN模型,成功地对交通标志分类器进行分类,准确率达96%。开发了一款交通标志识别应用程序,该应用程序具有图片识别和网络摄像头实时识别两种工作方式。
小白学视觉
2022/12/28
3.4K0
手把手教你使用CNN进行交通标志识别(已开源)
如何使用900万张开放图像训练600类图片分类器
如果你正在尝试构建一个图片分类器,但是需要训练集,你最好的选择是查看 Google Open Images 。
AI研习社
2019/07/15
1.1K0
如何使用900万张开放图像训练600类图片分类器
手把手搭建一个【卷积神经网络】
本文介绍卷积神经网络的入门案例,通过搭建和训练一个模型,来对10种常见的物体进行识别分类;使用到CIFAR10数据集,它包含10 类,即:“飞机”,“汽车”,“鸟”,“猫”,“鹿”, “狗”,“青蛙”,“马”,“船”,“卡车” ;共 60000 张彩色图片;通过搭建和训练卷积神经网络模型,对图像进行分类,能识别出图像是“汽车”,或“鸟”,还是其它。
一颗小树x
2021/05/12
1.5K0
手把手搭建一个【卷积神经网络】
自动驾驶汽车的交通标志识别
由于特斯拉等公司在电动汽车自动化方面的努力,无人驾驶汽车正变得非常受欢迎。为了成为5级自动驾驶汽车,这些汽车必须正确识别交通标志并遵守交通规则。在识别出这些交通标志之后,它还应该能够适当地做出正确的决定。
代码医生工作室
2020/02/21
1.6K0
自动驾驶汽车的交通标志识别
使用Python实现深度学习模型:智能垃圾分类与回收系统
智能垃圾分类与回收系统通过深度学习技术,可以自动识别和分类不同类型的垃圾,提高垃圾回收效率,减少环境污染。本文将介绍如何使用Python和深度学习技术来实现智能垃圾分类与回收系统。
Echo_Wish
2024/08/20
5420
使用Python实现深度学习模型:智能垃圾分类与回收系统
使用Python实现深度学习模型:智能身份验证与防伪
在当今数字化时代,身份验证和防伪技术变得尤为重要。深度学习作为人工智能的一个重要分支,提供了强大的工具来解决这些问题。本文将介绍如何使用Python实现一个基于深度学习的智能身份验证与防伪系统,详细讲解其基本原理和实现步骤。
Echo_Wish
2024/10/08
2580
使用Python实现深度学习模型:智能身份验证与防伪
独家 | 10分钟搭建你的第一个图像识别模型(附步骤、代码)
本文介绍了图像识别的深度学习模型的建立过程,通过陈述实际比赛的问题、介绍模型框架和展示解决方案代码,为初学者提供了解决图像识别问题的基础框架。
数据派THU
2019/03/08
1.7K0
独家 | 10分钟搭建你的第一个图像识别模型(附步骤、代码)
使用Python实现深度学习模型:智能安防监控与异常检测
在这篇教程中,我们将构建一个深度学习模型,用于智能安防监控和异常检测。我们将使用TensorFlow和Keras库来实现这一目标。通过这个教程,你将学会如何处理视频数据、构建和训练模型,并将模型应用于实际的异常检测任务。
Echo_Wish
2024/07/27
2950
使用Python实现深度学习模型:智能安防监控与异常检测
Transformers 4.37 中文文档(四)
www.youtube-nocookie.com/embed/KWwzcmG98Ds
ApacheCN_飞龙
2024/06/26
5230
Transformers 4.37 中文文档(四)
使用卷积神经网络预防疲劳驾驶事故
美国国家公路交通安全管理局估计,每年有 91,000 起车祸涉及疲劳驾驶的司机,造成约50,000 人受伤和近 800 人死亡。此外,每 24 名成年司机中就有 1 人报告在过去 30 天内在驾驶时睡着了。研究甚至发现,超过20个小时不睡觉相当于血液酒精浓度为0.08%——美国的法律规定的上限。
小白学视觉
2021/10/14
5110
基于卷积神经网络的人脸识别[通俗易懂]
利用opencv获取人脸,采集人脸数据,将收集到的人脸数据加载到内存,搭建属于自己的卷积神经网络,并用人脸数据训练自己的网络,将训练好的网络保存成模型,最后再用opencv获取实时人脸用先前训练好的模型来识别人脸。
全栈程序员站长
2022/09/06
1.3K0
基于卷积神经网络的人脸识别[通俗易懂]
探究肺癌患者的CT图像的图像特征并构建一个诊断模型
准备工作: 1.准备肺癌或非肺癌每个各10张图,在本地创建一个名为“data”的文件夹,用于存放数据集。在“data”文件夹下创建两个子文件夹,分别命名为“cancer”和“non_cancer”,用于存放肺癌和非肺癌图像。将10张肺癌图像命名为“cancer_1.jpg”到“cancer_10.jpg”,并将它们放入“cancer”文件夹中。将10张非肺癌图像命名为“non_cancer_1.jpg”到“non_cancer_10.jpg”,并将它们放入“non_cancer”文件夹中。
未名编程
2024/10/12
1960
探究肺癌患者的CT图像的图像特征并构建一个诊断模型
基于 Keras 和 dlib 的人脸识别实践
这次的实践是基于很小的数据集,搭建的系统也比较粗糙,只是个toy implementation。主要用来练手和熟悉流程的。
caoqi95
2019/03/27
1.2K0
基于 Keras 和 dlib 的人脸识别实践
“花朵分类“ 手把手搭建【卷积神经网络】
本文介绍卷积神经网络的入门案例,通过搭建和训练一个模型,来对几种常见的花朵进行识别分类;
一颗小树x
2021/05/13
2.1K0
“花朵分类“ 手把手搭建【卷积神经网络】
使用Python实现图像分类与识别模型
图像分类与识别是计算机视觉中的重要任务,它可以帮助我们自动识别图像中的对象、场景或者特征。在本文中,我们将介绍图像分类与识别的基本原理和常见的实现方法,并使用Python来实现这些模型。
Echo_Wish
2024/04/23
1.1K0
使用Python实现深度学习模型:智能垃圾分类与环境保护
智能垃圾分类是实现环境保护和资源回收的重要手段。通过深度学习技术,我们可以自动识别和分类垃圾,从而提高垃圾处理的效率。本文将介绍如何使用Python和深度学习库TensorFlow与Keras来构建一个简单的垃圾分类模型。
Echo_Wish
2024/08/07
3510
使用Python实现深度学习模型:智能垃圾分类与环境保护
Google全新AI实战课发布:从原理到代码,手把手带你入门机器学习
安妮 岳排槐 发自 凹非寺 量子位 出品 | 公众号 QbitAI 如果你的心里只有一件事。 请问:是不是学习? Google希望你是,而且还准备扶上马,再送一程。 所以今天一早,大礼包又来了。 手把手教你 今年春天,Google发布了机器学习速成课,英文简称MLCC。而且这套基本全程都有中文的课程,还是完全免费的。 这还不够。 Google觉得光学理论还不够,必须教你理论与实战相结合。 所谓:知行合一。 于是,Google发布了最新的一套课程:
量子位
2018/07/20
7550
独家 | 手把手教你用Python构建你的第一个多标签图像分类模型(附案例)
翻译:吴金笛 校对:郑滋 本文约4600字,建议阅读12分钟。 本文明确了多标签图像分类的概念,并讲解了如何构建多标签图像分类模型。 介绍 你正在处理图像数据吗?我们可以使用计算机视觉算法来做很多事情
数据派THU
2019/05/17
1.9K0
独家 | 手把手教你用Python构建你的第一个多标签图像分类模型(附案例)
使用Python实现深度学习模型:视频处理与动作识别
视频处理与动作识别是计算机视觉中的重要任务,广泛应用于监控系统、智能家居、体育分析等领域。通过使用Python和深度学习技术,我们可以构建一个简单的动作识别系统。本文将介绍如何使用Python实现视频处理与动作识别,并提供详细的代码示例。
Echo_Wish
2024/07/16
7510
使用Python实现深度学习模型:视频处理与动作识别
小狗分类器,你家的狗子是个什么狗?
这就是所谓的「机器学习」,让机器自己去“学习”。我们今天要做的这个分类任务,是一个“监督学习”的过程。
小小詹同学
2019/08/28
5590
小狗分类器,你家的狗子是个什么狗?
推荐阅读
相关推荐
手把手教你使用CNN进行交通标志识别(已开源)
更多 >
LV.0
深圳魔图互联科技有限公司算法工程师
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验