JAVASE02-Unit010: 多线程基础 、 TCP通信

    多线程基础 、 TCP通信    

* 当一个方法被synchronized修饰后,那么
 * 该方法称为同步方法,即:多个线程不能同时
 * 进入到方法内部执行。

package day10;
/**
 * 当多线程并发操作同一资源时,由于线程切换的不确定
 * 性,可能导致执行顺序的混乱,严重时可能导致系统
 * 瘫痪。
 * @author adminitartor
 *
 */
public class SyncDemo1 {
    public static void main(String[] args) {
        final Table table = new Table();
        Thread t1 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();
                    Thread.yield();//模拟线程切换
                    System.out.println(getName()+":"+bean);
                }
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();
                    Thread.yield();//模拟线程切换
                    System.out.println(getName()+":"+bean);
                }
            }
        };

        t1.start();
        t2.start();
    }
}

class Table{
    private int beans = 20;
    /**
     * 当一个方法被synchronized修饰后,那么
     * 该方法称为同步方法,即:多个线程不能同时
     * 进入到方法内部执行。
     * 在方法上使用synchronized那么锁对象为
     * 当前方法所属对象,即:this
     * @return
     */
    public synchronized int getBean(){
        if(beans==0){
            throw new RuntimeException("没有豆子了!");
        }
        Thread.yield();//模拟线程切换
        return beans--;
    }
}

SyncDemo1.java

* 有效的缩小同步范围可以在保证并发安全的前提下
 * 提高并发效率。

package day10;
/**
 * 有效的缩小同步范围可以在保证并发安全的前提下
 * 提高并发效率。
 * @author adminitartor
 *
 */
public class SyncDemo2 {
    public static void main(String[] args) {
        final Shop shop = new Shop();
        Thread t1 = new Thread(){
            public void run(){
                shop.buy();
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                shop.buy();
            }
        };
        t1.start();
        t2.start();
    }
}

class Shop{
    public void buy(){
        try {
            Thread t = Thread.currentThread();
            System.out.println(t.getName()+":正在挑选衣服...");
            Thread.sleep(5000);
            /*
             * 多个线程要保证同步执行代码的前提是
             * 这里看到的"同步监视器"即:上锁的对象
             * 是同一个。
             */
            synchronized(this){
                System.out.println(t.getName()+":正在试衣服...");
                Thread.sleep(5000);
            }
            System.out.println(t.getName()+":结账离开");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

SyncDemo2.java

* 每个类在被JVM加载时,JVM都会创建一个且只创建
 * 一个Class类型的实例来表示它。所以,每个类在
 * JVM内部都有唯一的一个Class类型的实例对应,而
 * 静态方法就是将该Class的实例上锁的。

package day10;
/**
 * 静态方法若使用synchronized修饰后,那么该方法
 * 一定具有同步效果。
 * 静态方法的同步监视器对象为当前类的类对象。
 * 类对象:Class类型的实例。
 * 每个类在被JVM加载时,JVM都会创建一个且只创建
 * 一个Class类型的实例来表示它。所以,每个类在
 * JVM内部都有唯一的一个Class类型的实例对应,而
 * 静态方法就是将该Class的实例上锁的。
 * @author adminitartor
 *
 */
public class SyncDemo3 {
    public static void main(String[] args) {
        Thread t1 = new Thread(){
            public void run(){
                Foo.dosome();
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                Foo.dosome();
            }
        };
        t1.start();
        t2.start();
    }
}

class Foo{
    public synchronized static void dosome(){
        try {
            Thread t = Thread.currentThread();
            System.out.println(t.getName()+":正在运行dosome方法...");
            Thread.sleep(5000);
            System.out.println(t.getName()+":运行dosome方法完毕!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

SyncDemo3.java

* 互斥锁

package day10;
/**
 * 互斥锁
 * 当使用Synchronized修饰多段不同代码,但是同步
 * 监视器对象是同一个的时候,那么这些代码间就具有
 * 了互斥性,同一时间不能同时执行这些代码。
 * @author adminitartor
 *
 */
public class SyncDemo4 {
    public static void main(String[] args) {
        final Boo boo = new Boo();
        Thread t1 = new Thread(){
            public void run(){
                boo.methodA();
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                boo.methodB();
            }
        };
        t1.start();
        t2.start();
     }
}

class Boo{
    public void methodA(){
        synchronized(this){
            try {
                Thread t = Thread.currentThread();
                System.out.println(
                 t.getName()+":正在执行A方法");
                Thread.sleep(5000);
                System.out.println(
                 t.getName()+":执行A方法完毕");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public void methodB(){
        synchronized(this){
            try {
                Thread t = Thread.currentThread();
                System.out.println(t.getName()+":正在执行B方法");
                Thread.sleep(5000);
                System.out.println(t.getName()+":执行B方法完毕");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

SyncDemo4.java

* 死锁

package day10;
/**
 * 死锁
 * 双方都持有自己的锁,但都要求对方先释放锁时
 * 出现死锁现象。
 * @author adminitartor
 *
 */
public class SyncDemo5 {
    public static void main(String[] args) {
        final Coo coo = new Coo();
        Thread t1 = new Thread(){
            public void run(){
                coo.methodA();
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                coo.methodB();
            }
        };
        t1.start();
        t2.start();
    }
}

class Coo{
    private Object lockA = new Object();
    private Object lockB = new Object();

    public void methodA(){
        try {
            Thread t = Thread.currentThread();
            synchronized (lockA) {
                System.out.println(t.getName()+"正在运行A方法");
                Thread.sleep(5000);
                methodB();
                System.out.println(t.getName()+"运行A方法完毕");
            }

        } catch (Exception e) {
        }
    }
    public void methodB(){
        try {
            Thread t = Thread.currentThread();
            synchronized (lockB) {
                System.out.println(t.getName()+"正在运行B方法");
                Thread.sleep(5000);
                methodA();
                System.out.println(t.getName()+"运行B方法完毕");
            }

        } catch (Exception e) {
        }
    }
}

SyncDemo5.java

* 使用Collections的静态方法可以将现有的集合
 * 或Map转换为线程安全的

package day10;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 使用Collections的静态方法可以将现有的集合
 * 或Map转换为线程安全的
 * @author adminitartor
 *
 */
public class Sync_API {
    public static void main(String[] args) {
        /*
         * 线程安全的集合自身的add,remove等方法
         * 都是同步的,并且之间也有互斥。
         * 但是并不与迭代器遍历互斥。所以若并发
         * 同时遍历和增删元素,迭代器依然会抛出
         * 异常。
         * 所以,迭代器与集合元素操作间要自行维护
         * 互斥关系。
         *
         * ArrarList,LinkedList都不是线程安全的
         */
        List<String> list
            = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        System.out.println(list);
        //将给定的集合转换为一个线程安全的集合
        list = Collections.synchronizedList(list);

        System.out.println(list);

        Set<String> set
            = new HashSet<String>(list);
        set = Collections.synchronizedSet(set);
        System.out.println(set);

        Map<String,Integer> map
            = new HashMap<String,Integer>();
        map.put("语文", 100);
        map.put("数学", 99);
        map.put("英语", 98);

        map = Collections.synchronizedMap(map);
        System.out.println(map);
    }
}

Sync_API.java

* 线程池

package day10;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 线程池
 * 线程池有两个主要作用:
 * 1:控制线程数量
 * 2:重用线程
 * @author adminitartor
 *
 */
public class ThreadPool_Demo {
    public static void main(String[] args) {
        ExecutorService threadPool
            = Executors.newFixedThreadPool(2);

        for(int i=0;i<5;i++){
            Runnable runn = new Runnable(){
                public void run(){
                    Thread t = Thread.currentThread();
                    System.out.println(t.getName()+":正在运行任务...");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(t.getName()+":运行任务完毕!");
                }
            };
            threadPool.execute(runn);
        }

        //结束线程池
        threadPool.shutdown();
        System.out.println("线程池结束了!");
    }
}

ThreadPool_Demo.java

案例一:

* 封装了TCP通讯的Socket
 * 使用它可以与服务端建立连接,并进行通讯

package chat;

import java.net.Socket;

/**
 * 聊天室客户端
 * @author adminitartor
 *
 */
public class Client {
    /*
     * 封装了TCP通讯的Socket
     * 使用它可以与服务端建立连接,并进行通讯
     *
     */
    private Socket socket;
    /**
     * 构造方法,用来初始化客户端
     */
    public Client() throws Exception{
        /*
         * 实例化Socket的过程就是连接服务端的
         * 过程。若连接失败,这里会抛出异常
         *
         * 构造方法的两个参数:
         * 1:服务端计算机的IP地址
         * 2:服务端应用程序的端口
         */
        socket = new Socket(
            "localhost",8088
        );
    }
    /**
     * 客户端开始工作的方法
     */
    public void start(){

    }

    public static void main(String[] args) {
        try {
            Client client = new Client();
            client.start();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("客户端运行失败!");
        }
    }
}

Client.java

* 聊天室服务端

package chat;

import java.net.ServerSocket;
import java.net.Socket;

/**
 * 聊天室服务端
 * @author adminitartor
 *
 */
public class Server {
    /*
     * 运行在服务端的ServerSocket,主要作用:
     * 1:向操作系统申请服务端口,客户端就是通过
     *   这个端口与服务端程序建立连接的
     * 2:监听服务端口,一旦客户端连接了,就会创建
     *   一个Socket以便与该客户端交互
     */
    private ServerSocket server;

    /**
     * 构造方法,用来初始化服务端
     * @throws Exception
     */
    public Server() throws Exception{
        /*
         * 初始化,并申请服务端口,若该端口被
         * 其他应用程序占用,这里会抛出异常
         */
        server = new ServerSocket(8088);
    }

    public void start(){
        try {
            /*
             * ServerSocket提供方法:
             * Socket accept()
             * 该方法是一个阻塞方法,直到一个客户端
             * 通过申请的端口连接上,这里才会返回
             * 返回的是一个Socket实例,通过该实例
             * 即可与刚连接的客户端交互。
             */
            System.out.println("等待客户端连接...");
            Socket socket = server.accept();
            System.out.println("一个客户端连接了!");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try {
            Server server = new Server();
            server.start();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("服务端运行失败!");
        }
    }
}

Server.java

时间: 01-04

JAVASE02-Unit010: 多线程基础 、 TCP通信的相关文章

Java基础教程:多线程基础(2)——线程间的通信

Java基础教程:多线程基础(2)--线程间的通信 使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督. 线程间的通信 思维导图 等待中 等待/通知机制 不使用等待/通知机制 我们可以使用使用sleep()与 whle(true) 死循环来实现多个线程间的通信. 虽然两个线程实现了通信,但是线程B必须不断的通过while语句轮训机制来检测某一个条件,这样会浪费CPU资源. 如果轮询间隔较小,更浪费时间间隔.如果轮训

TCP通信 - 服务器开启多线程与read()导致服务器阻塞问题

TCP通信的文件上传案例 本地流:客户端和服务器和本地硬盘进行读写,需要使用自己创建的字节流 网络流:客户端和服务器之间读写,必须使用Socket中提供的字节流对象 客户端工作:读取本地文件,上传到服务器,读取服务器回写的数据 明确数据源 目的地:服务器 客户端代码: package cn.learn.web; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; impor

多线程 基础

进程 什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcode,系统就会分别启动2个进程 通过"活动监视器"可以查看Mac系统中所开启的进程 线程 什么是线程 1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程) 线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行 比如使用酷狗播放音乐.使用迅雷下载电影,都需要在线程中执行 线程的串行 1个线程中任务的执行是串行的 如果

多线程基础(五)

5.多线程基础 线程间通信 什么叫线程间通信 在一个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另一个线程 在1个线程中执行完特定任务后, 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 线程间通信常用方法  perform执行 selector选择器 - (void)performSelectorOnMainThread:(SEL)aSelectorwithObject:(id)ar

Java多线程基础

1. 前言 这篇文章,是对Java多线程编程的基础性介绍. 文章将介绍Java语言为支持多线程编程提供的一些特性.通过这篇文章,您将了解到如何通过Java语言创建一个线程,如何通过内置的锁来实现线程间的同步,如何在线程间进行通信以及线程的中断机制. 2. 什么是线程 线程是操作系统调度的最小单位,在一个进程中,一般至少有一个线程在运行.一个进程中包含的多个线程,在多核处理器中,操作系统可以将多个线程调度到不同的CPU核心上运行,多个线程可以并行运行. 在同一个进程中的多个线程,共享同一个进程空间

异步tcp通信——APM.Core 服务端概述

为什么使用异步 异步线程是由线程池负责管理,而多线程,我们可以自己控制,当然在多线程中我们也可以使用线程池.就拿网络扒虫而言,如果使用异步模式去实现,它使用线程池进行管理.异步操作执行时,会将操作丢给线程池中的某个工作线程来完成.当开始I/O操作的时候,异步会将工作线程还给线程池,这意味着获取网页的工作不会再占用任何CPU资源了.直到异步完成,即获取网页完毕,异步才会通过回调的方式通知线程池.可见,异步模式借助于线程池,极大地节约了CPU的资源. 注:DMA(Direct Memory Acce

Java多线程基础(四)Java传统线程同步通信技术

Java多线程基础(四)Java传统线程同步通信技术 编写代码实现以下功能 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次. 分析 1)子线程循环10次与主线程循环100次必须是互斥的执行,不能出现交叉,下面代码中通过synchronized关键字实现此要求: 2)子线程与主线程必须交替出现,可以通过线程同步通信技术实现,下面代码中通过bShouldSub变量实现此要求: 其他需要注意的地方 1)其中business变量必须声

qt 之 TCP 通信代码及解释

服务器: #include "server.h" #include "ui_server.h" Server::Server(QWidget *parent) :     QWidget(parent),     ui(new Ui::Server) {     m_tcpServer = new QTcpServer(this);     //注意,这里的变量是在.h文件中声明的,是一个指针,在头文件中应该包含QTcpServer 这个类,而且在工程文件中应该加入

iOS开发多线程基础知识

--------------------------多线程概念基础------- 进程:正在运行的程序 内存:每个进程所占的存储空间 线程:1个进程要像执行任务,必须得有线程,线程是进程的基本执行单元, 线程的串行: ·1个线程中人物的执行是串行的 ·0同一个时间内,1个线程只能执行1个任务 0·线程是进程的一条执行路径 --------多线程 ·一个进程中可以开启多条线程,每条线程可以并行(同时)同时执行不同的任务 ·进程->车间 线程->车间工人 线程的并行: ·进程内多个线程同时执行,可