rewrite whole the code to Java

package main

import (
    "bufio"
    "fmt"
    "io"
    "log"
    "math/rand"
    "net"
    "os"
    "strconv"
    "strings"
    "sync"
    "time"
)

type ProxyPool struct {
    address  string
    conns    chan net.Conn
    maxConns int
}

func NewProxyPool(address string, maxConns int) *ProxyPool {
    return &ProxyPool{
        address:  address,
        conns:    make(chan net.Conn, maxConns),
        maxConns: maxConns,
    }
}

func (p *ProxyPool) GetConn() (net.Conn, error) {
    select {
    case conn := <-p.conns:
        if isConnAlive(conn) {
            return conn, nil
        }
        conn.Close()
    default:
    }
    return p.newConn()
}

func (p *ProxyPool) newConn() (net.Conn, error) {
    dialer := &net.Dialer{
        Timeout:   5 * time.Second,
        KeepAlive: 30 * time.Second,
    }
    conn, err := dialer.Dial("tcp", p.address)
    if err != nil {
        return nil, err
    }
    return conn, nil
}

func (p *ProxyPool) PutConn(conn net.Conn) {
    select {
    case p.conns <- conn:
    default:
        conn.Close()
    }
}

func isConnAlive(conn net.Conn) bool {
    tcpConn, ok := conn.(*net.TCPConn)
    if !ok {
        return false
    }
    err := tcpConn.SetReadDeadline(time.Now().Add(1 * time.Millisecond))
    if err != nil {
        return false
    }
    defer tcpConn.SetReadDeadline(time.Time{})
    var buf [1]byte
    if _, err := conn.Read(buf[:]); err == io.EOF {
        return false
    }
    return true
}

func logError(err error) {
    if err != nil {
        file, logErr := os.OpenFile("error.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
        if logErr == nil {
            defer file.Close()
            logger := log.New(file, "", log.LstdFlags)
            logger.Println(err)
        }
    }
}

type HttpProxy struct {
    proxyList           []string
    proxyPools          map[string]*ProxyPool
    proxyPoolsMu        sync.RWMutex
    host                string
    startPort           int
    endPort             int
    proxyUpdateInterval time.Duration
    mu                  sync.RWMutex
    rand                *rand.Rand
    whitelistIPs        map[string]struct{}
    blockedKeywords     []string
    bufferPool          sync.Pool
}

func NewHttpProxy(proxyList []string, host string, startPort, endPort int) *HttpProxy {
    proxyPools := make(map[string]*ProxyPool)
    for _, proxy := range proxyList {
        proxyPools[proxy] = NewProxyPool(proxy, 1000)
    }
    return &HttpProxy{
        proxyList:           proxyList,
        proxyPools:          proxyPools,
        host:                host,
        startPort:           startPort,
        endPort:             endPort,
        proxyUpdateInterval: 1 * time.Minute,
        rand:                rand.New(rand.NewSource(time.Now().UnixNano())),
        blockedKeywords:     []string{"gov", "mil", "kremlin", "government", "cikrf", "mos.ru", "bankofamerica", "gosuslugi"},
        bufferPool: sync.Pool{
            New: func() interface{} {
                return make([]byte, 32*1024)
            },
        },
        whitelistIPs: make(map[string]struct{}),
    }
}

func (p *HttpProxy) getRandomProxy() string {
    p.mu.RLock()
    defer p.mu.RUnlock()
    return p.proxyList[p.rand.Intn(len(p.proxyList))]
}

func (p *HttpProxy) loadWhitelist() {
    content, err := os.ReadFile("whitelist.txt")
    if err != nil {
        logError(err)
        return
    }
    lines := strings.Split(string(content), "\n")
    p.mu.Lock()
    defer p.mu.Unlock()
    p.whitelistIPs = make(map[string]struct{})
    for _, line := range lines {
        ip := strings.TrimSpace(line)
        if ip != "" {
            p.whitelistIPs[ip] = struct{}{}
        }
    }
}

func (p *HttpProxy) handleClient(clientConn net.Conn) {
    defer clientConn.Close()
    if tcpConn, ok := clientConn.(*net.TCPConn); ok {
        tcpConn.SetKeepAlive(true)
        tcpConn.SetKeepAlivePeriod(30 * time.Second)
    }
    clientAddr := clientConn.RemoteAddr().String()
    clientIP, _, err := net.SplitHostPort(clientAddr)
    if err != nil {
        logError(err)
        return
    }
    p.mu.RLock()
    _, ipInWhitelist := p.whitelistIPs[clientIP]
    p.mu.RUnlock()
    if !ipInWhitelist {
        return
    }
    buffer := p.bufferPool.Get().([]byte)
    defer p.bufferPool.Put(buffer)
    n, err := clientConn.Read(buffer)
    if err != nil {
        logError(err)
        return
    }
    request := string(buffer[:n])
    lines := strings.Split(request, "\n")
    if len(lines) == 0 {
        return
    }
    firstLine := lines[0]
    urlParts := strings.Split(firstLine, " ")
    if len(urlParts) < 2 {
        return
    }
    url := urlParts[1]
    temp := url
    if idx := strings.Index(url, "://"); idx != -1 {
        temp = url[idx+3:]
    }
    if idx := strings.Index(temp, "/"); idx != -1 {
        temp = temp[:idx]
    }
    for _, keyword := range p.blockedKeywords {
        if strings.Contains(strings.ToLower(temp), keyword) {
            return
        }
    }
    var proxyConn net.Conn
    var proxy string
    attempts := 0
    for attempts < 3 {
        proxy = p.getRandomProxy()
        p.proxyPoolsMu.RLock()
        pool, ok := p.proxyPools[proxy]
        p.proxyPoolsMu.RUnlock()
        if !ok {
            attempts++
            continue
        }
        proxyConn, err = pool.GetConn()
        if err == nil {
            break
        }
        attempts++
    }
    if proxyConn == nil {
        return
    }
    if tcpConn, ok := proxyConn.(*net.TCPConn); ok {
        tcpConn.SetKeepAlive(true)
        tcpConn.SetKeepAlivePeriod(30 * time.Second)
    }
    defer func() {
        p.proxyPoolsMu.RLock()
        pool, ok := p.proxyPools[proxy]
        p.proxyPoolsMu.RUnlock()
        if ok {
            pool.PutConn(proxyConn)
        } else {
            proxyConn.Close()
        }
    }()
    _, err = proxyConn.Write(buffer[:n])
    if err != nil {
        logError(err)
        return
    }
    done := make(chan struct{}, 2)
    go func() {
        defer func() { done <- struct{}{} }()
        buf := p.bufferPool.Get().([]byte)
        defer p.bufferPool.Put(buf)
        _, err := io.CopyBuffer(proxyConn, clientConn, buf)
        if err != nil {
            logError(err)
        }
    }()
    go func() {
        defer func() { done <- struct{}{} }()
        buf := p.bufferPool.Get().([]byte)
        defer p.bufferPool.Put(buf)
        _, err := io.CopyBuffer(clientConn, proxyConn, buf)
        if err != nil {
            logError(err)
        }
    }()
    <-done
    <-done
}

func (p *HttpProxy) updateProxies() {
    for {
        file, err := os.Open("out.txt")
        if err != nil {
            logError(err)
            time.Sleep(p.proxyUpdateInterval)
            continue
        }
        scanner := bufio.NewScanner(file)
        var newProxyList []string
        for scanner.Scan() {
            newProxyList = append(newProxyList, scanner.Text())
        }
        if err := scanner.Err(); err != nil {
            logError(err)
        }
        file.Close()
        if len(newProxyList) > 0 {
            p.mu.Lock()
            p.proxyList = newProxyList
            p.mu.Unlock()
            p.updateProxyPools(newProxyList)
        }
        time.Sleep(p.proxyUpdateInterval)
    }
}

func (p *HttpProxy) updateProxyPools(newProxyList []string) {
    p.proxyPoolsMu.Lock()
    defer p.proxyPoolsMu.Unlock()
    newProxyPools := make(map[string]*ProxyPool)
    for _, proxy := range newProxyList {
        if pool, exists := p.proxyPools[proxy]; exists {
            newProxyPools[proxy] = pool
        } else {
            newProxyPools[proxy] = NewProxyPool(proxy, 1000)
        }
    }
    for proxy, pool := range p.proxyPools {
        if _, exists := newProxyPools[proxy]; !exists {
            close(pool.conns)
            for conn := range pool.conns {
                conn.Close()
            }
        }
    }
    p.proxyPools = newProxyPools
}

func (p *HttpProxy) start() {
    p.loadWhitelist()
    go func() {
        ticker := time.NewTicker(1 * time.Minute)
        for range ticker.C {
            p.loadWhitelist()
        }
    }()
    go p.updateProxies()
    for port := p.startPort; port <= p.endPort; port++ {
        go func(port int) {
            listener, err := net.Listen("tcp", p.host+":"+strconv.Itoa(port))
            if err != nil {
                logError(err)
                return
            }
            defer listener.Close()
            for {
                clientConn, err := listener.Accept()
                if err != nil {
                    logError(err)
                    continue
                }
                go p.handleClient(clientConn)
            }
        }(port)
    }
    select {}
}

func main() {
    file, err := os.Open("out.txt")
    if err != nil {
        logError(err)
        return
    }
    defer file.Close()
    scanner := bufio.NewScanner(file)
    var proxyList []string
    for scanner.Scan() {
        proxyList = append(proxyList, scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        logError(err)
    }
    if len(proxyList) == 0 {
        logError(fmt.Errorf("proxy list is empty"))
        return
    }
    proxyServer := NewHttpProxy(proxyList, "0.0.0.0", 47858, 47859)
    proxyServer.start()
}