Tag Archives: 多线程

Socket通讯的简单实现与应用(文件上传)

Socket通讯的基本实现

package com.yusian.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketDemo {
    public static void main(String[] args) {
        // 服务端进程
        new Thread(() -> {
            try {
                // 创建一个Socket服务
                ServerSocket ss = new ServerSocket(8080);
                // 获取Socket的字节输入流对象,此时程序会阻塞在这个位置,直到有数据
                InputStream is = ss.accept().getInputStream();
                int data = 0;
                // 将接收到的数据输出到控制台
                while ((data = is.read()) != -1) {
                    System.out.print((char) data);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        // 客户端进程
        new Thread(() -> {
            try {
                // 创建一个Socket客户端,连接到指定服务器
                Socket s = new Socket("localhost", 8080);
                // 获取Socket的字节输出流,将数据从这里发出
                OutputStream os = s.getOutputStream();
                os.write("Hello Socket...".getBytes());
                // 注意:要主动结束数据发送,否则对方会一直处于等待状态
                s.shutdownOutput();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

[……]

继续阅读

线程间通讯之【生产者&消费者】模型

  • 同步:线程间通讯要确保同步执行;
  • 同锁:线程间同步机制锁需要是同一个对象,才能保证同步,可以通过synchronized关键字或Lock来实现;
  • 轮询:通过while或其他循环方法来获取当前状态,是该等待还是通知对方;
  • 通讯:所谓的通讯其实是通过共用锁的waitnotify方法来实现的;

商品对象类

/**
 * 商品描述类,当前只是简单地标记商品的有与无
 */
public class Goods {
    // 是否还有库存
    boolean isEmpty;

    public Goods() {
        this.isEmpty = true;
    }
}

消费者

/**
 * 消费者模型
 */
public class Consumer extends Thread {
    Goods goods;

    public Consumer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        // 循环检测
        while (true) {
            // 同步执行
            synchronized (goods) {
                // 如果库存不为空则开始消费,消费结束后,将库存标记为空
                if (!goods.isEmpty) {
                    System.out.println("---------------------");
                    System.out.println("消费");
                    try {
                        Thread.sleep(1000);
                        System.out.println("...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("需求");
                    goods.isEmpty = true;
                }
                // 通知生产,当前线程等待,直接到生产唤醒
                goods.notify();
                try {
                    goods.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

生产者
[……]

继续阅读

多线程并发服务器程序

1、server.c

#include "wrap.h"
#include <pthread.h>
#include <ctype.h>
#include <strings.h>

void *callback(void *arg)
{
    int *cfd = (int *)arg;
    printf("pthread %ld running...\n", pthread_self());
    while(1){
        char buf[BUFSIZ];
        int n = Readn(*cfd, buf, BUFSIZ);
        if (n <= 0){
            close(*cfd);
            pthread_exit(NULL);
        }
        int i = n;
        while(i--){
            buf[i] = toupper(buf[i]);
        }
        write(*cfd, buf, n);
    }
    return NULL;
}
#define SEV_PORT 3000
int main(){
    // 1、socket
    int sfd = Socket(AF_INET, SOCK_STREAM, 0);
    // 2、bind
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(SEV_PORT);
    Bind(sfd, &addr, sizeof(addr));
    // 3、listen
    Listen(sfd, 128);
    // 4、accept
    int cfds[256];
    int n = 0;
    while(1){
        struct sockaddr_in c_addr;
        socklen_t len = sizeof(c_addr);
        bzero(&c_addr, sizeof(c_addr));
        cfds[n] = Accept(sfd, &c_addr, &len);
        char buf[BUFSIZ];
        printf("Client connected -- ip:%s, port:%d\n", inet_ntop(AF_INET, &c_addr.sin_addr.s_addr, buf, BUFSIZ), ntohs(c_addr.sin_port));
        pthread_t thread;
        int ret = pthread_create(&thread, NULL, callback, cfds + n);
        if (ret < 0){
            perror("pthread create error");
            exit(1);
        }
        n++;
        pthread_detach(thread);
    }
}

wrap.h[……]

继续阅读

文件读写操作中锁的使用

1、简述
1.1、多线程操作中必然会涉及到锁的概念,使用锁来确保线程安全;
1.2、事实上某些操作,比如数据读取是可以允许多线程同时操作的;
1.3、但写操作不行,数据写入动作必须是同步的,否则会出现数据错误;
1.4、如果读、写操作动作同时发生,并且多线程并发操作时该如何处理?
1.5、通过普通加锁实现线程同步,这样线程是安全了,但影响了读取的效率;
1.6、基本思路是
1.6.1、允许读取操作多线程并发进行;
1.6.2、写入操作只能单个线程同步进行;
1.7、常用的解决方案有两个
1.7.1、pthread_rwlock
1.7.2、dispatch_barrier_async

2、代码示例
2.1、pthread_rwlock[……]

继续阅读