多线程基础 、 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

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

  1. 性能测试基础 ---TCP通信过程的状态码与过程,以及出现错误码的分析(TIME_WAIT,CLOSE_WAIT)

    TCP通信过程 如下图所示,TCP通信过程包括三个步骤:建立TCP连接通道(三次握手).数据传输.断开TCP连接通道(四次挥手). 这里进一步探究TCP三路握手和四次挥手过程中的状态变迁以及数据传输过 ...

  2. 多线程基础(五)NSThread线程通信

    5.多线程基础 线程间通信   什么叫线程间通信 在一个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信   线程间通信的体现 1个线程传递数据给另一个线程 在1个线程中执行完特定任务后, ...

  3. UE4 Sockets多线程TCP通信

    转自:https://blog.csdn.net/zilisen/article/details/75007447 一.简介 UE4引擎是提供了Sockets模块和Networking模块的,博主在研 ...

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

    Java基础教程:多线程基础(2)——线程间的通信 使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督. 线程间的通信 ...

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

    TCP通信的文件上传案例 本地流:客户端和服务器和本地硬盘进行读写,需要使用自己创建的字节流 网络流:客户端和服务器之间读写,必须使用Socket中提供的字节流对象 客户端工作:读取本地文件,上传到服 ...

  6. TCP通信---文件上传案例、多线程文件上传

    目前大多数服务器都会提供文件上传的功能,由于文件上传需要数据的安全性和完整性,很明显需要使用TCP协议来实现. TCP通信需要创建一个服务器端程序和一个客户端程序,实现客户端向服务器端上传文件 代码实 ...

  7. 【Java TCP/IP Socket】深入剖析socket——TCP通信中由于底层队列填满而造成的死锁问题(含代码)

    基础准备 首先需要明白数据传输的底层实现机制,在http://blog.csdn.net/ns_code/article/details/15813809这篇博客中有详细的介绍,在上面的博客中,我们提 ...

  8. 多线程实现tcp聊天服务器

    多线程tcp  server & client tcp服务端(多线程): from socket import * from threading import Thread def clien ...

  9. Java进阶:基于TCP通信的网络实时聊天室

    目录 开门见山 一.数据结构Map 二.保证线程安全 三.群聊核心方法 四.聊天室具体设计 0.用户登录服务器 1.查看当前上线用户 2.群聊 3.私信 4.退出当前聊天状态 5.离线 6.查看帮助 ...

随机推荐

  1. mybatis 书写

    查询语句是使用 MyBatis 时最常用的元素之一 select元素配置细节如下 属性 描述 取值 默认 id 在这个模式下唯一的标识符,可被其它语句引用     parameterType 传给此语 ...

  2. request getParameter getAttribute

    在浏览器地址输入,表示传入一个参数test,值为123 http://localhost:8888/Test/index.jsp?test=123 在index.jsp中尝试使用EL表达式取出,代码如 ...

  3. 卸载 ibus 使Ubuntu16.04任务栏与启动器消失 问题解决

    经查证是unity误卸载了,我使用了命令: sudo apt-get remove --purge ibus 解决方法是: 使用以下命令:重置compiz: dconf reset -f /org/c ...

  4. 【Java EE 学习 34】【struts2学习第一天】

    一.struts2简介 struts2是一个用来开发MVC应用程序的框架.它提供了Web应用程序开发过程中的一些常见问题的解决方案. 1.struts2的作用域范围:三层架构当中的第一层,相当于MVC ...

  5. 简单Excel表格上传下载,POI

    一.废话 Excel表格是office软件中的一员,几乎是使用次数最多的办公软件.所以在java进行企业级应用开发的时候经常会用到对应的上传下载便利办公. 目前,比较常用的实现Java导入.导出Exc ...

  6. OSS层基础:平台区分

    #define PLATFORM_WINDOWS 1 #define PLATFORM_MAC 2 #define PLATFORM_UNIX 3 #if defined(_WIN32) #defin ...

  7. Unity Standard Assets 简介之 其他资源

    还有一些其他资源包,要不就是已经有Unity官方的介绍了,要不就是以资源为主没有多少脚本,最后集中说明一下. Effects资源包:包含各种图像特效,Unity官方文档地址 http://docs.u ...

  8. 【BZOJ】3561: DZY Loves Math VI

    题意 求\(\sum_{i=1}^{n} \sum_{j=1}^{m} lcm(i, j)^{gcd(i, j)}\)(\(n, m<=500000\)) 分析 很显然要死推莫比乌斯 题解 设\ ...

  9. easyUI-增删改查

    页面整体效果 首先是页面层: 因为数据中涉及到Date类型的字段,所以在一开始先做了一个拼装装换日期格式的方法 因为在easyUI的JSON解析的Data是一个long型的数字长串,关于解析的数字长串 ...

  10. 初用idea建立javaweb遇到的问题与心得

    1.直接用idea建立的web项目,其自动生成的web.xml里version=3.1,这样的话建立servlet-name等标签会报错(因为3.1不支持这种做法,更提倡用注解的办法),解决办法是将w ...